Browse files

final pre-release fixes for v0.1

  • Loading branch information...
1 parent 6f8b2de commit 1bae413efa8e45adf1652aaccad24fe21bded06f Mark Murphy committed Apr 21, 2012
Showing with 1,157 additions and 388 deletions.
  1. +1 −23 AndroidManifest.xml
  2. +69 −0 README.markdown
  3. +2 −0 demo/AndroidManifest.xml
  4. BIN libs/CWAC-LoaderEx.jar
  5. +0 −40 proguard.cfg
  6. +1 −2 project.properties
  7. +5 −0 res/layout/empub_image.xml
  8. +87 −0 res/layout/preference_widget_seekbar.xml
  9. +0 −9 res/menu/empub_actions.xml
  10. +24 −0 res/menu/empub_options.xml
  11. +6 −0 res/values-land/dimens.xml
  12. +6 −0 res/values-large/dimens.xml
  13. +6 −0 res/values-sw600dp-w1280dp/dimens.xml
  14. +10 −0 res/values-w720dp/dimens.xml
  15. +12 −0 res/values/dimens.xml
  16. +10 −1 res/values/strings.xml
  17. +9 −0 res/values/styles.xml
  18. +17 −0 res/xml/pref_display.xml
  19. +12 −0 res/xml/preference_headers.xml
  20. +20 −1 src/com/commonsware/empub/BookContents.java
  21. +50 −136 src/com/commonsware/empub/ChapterFragment.java
  22. +48 −0 src/com/commonsware/empub/ContentFragment.java
  23. +78 −0 src/com/commonsware/empub/ContentsAdapter.java
  24. +0 −51 src/com/commonsware/empub/ContentsLoader.java
  25. +80 −125 src/com/commonsware/empub/EmPubActivity.java
  26. +84 −0 src/com/commonsware/empub/ImageFragment.java
  27. +132 −0 src/com/commonsware/empub/ModelFragment.java
  28. +11 −0 src/com/commonsware/empub/NavListener.java
  29. +33 −0 src/com/commonsware/empub/Preferences.java
  30. +249 −0 src/com/commonsware/empub/SeekBarPreference.java
  31. +31 −0 src/com/commonsware/empub/SimpleContentActivity.java
  32. +34 −0 src/com/commonsware/empub/SimpleContentFragment.java
  33. +30 −0 src/com/commonsware/empub/StockPreferenceFragment.java
View
24 AndroidManifest.xml
@@ -5,28 +5,6 @@
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="11"/>
-
- <supports-screens
- android:largeScreens="true"
- android:normalScreens="true"
- android:smallScreens="false"
- android:xlargeScreens="true"/>
-
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/Theme.Sherlock"
- android:uiOptions="splitActionBarWhenNarrow">
- <activity android:name=".EmPubActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
-
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
+ <application />
</manifest>
View
69 README.markdown
@@ -0,0 +1,69 @@
+EmPub: Embedded Digital Book Reader
+===================================
+
+EmPub can display the contents of an EPUB file, packaged with
+EmPub itself in an APK.
+
+EmPub is packaged as an Android library project, so a hosting
+project can define things like error reporting, self-updating
+policies, and so forth. You will find a `demo/` sub-project
+that serves as a host, with some sample material serving as a book.
+
+This project is largely undocumented at the present time, though
+that will be rectified in the coming months.
+
+Usage
+-----
+TBD
+
+Dependencies
+------------
+This project relies upon [ActionBarSherlock](http://actionbarsherlock.com),
+so you will need to adjust the EmPub library project to have a reference
+to your own copy of the ActionBarSherlock library project.
+
+This library at present requires Android 2.2 (API Level 8) or
+higher. To *build* the library, you will need API Level 14, to be able
+to compile ActionBarSherlock.
+
+Version
+-------
+This is version v0.1 of this module, meaning that it is brand-spankin' new.
+
+Demo
+----
+In the `demo/` sub-project you will find
+a sample activity that demonstrates the use of EmPub.
+
+License
+-------
+The code in this project is licensed under the Apache
+Software License 2.0, per the terms of the included LICENSE
+file.
+
+Questions
+---------
+If you have questions regarding the use of this code, please post a question
+on [StackOverflow](http://stackoverflow.com/questions/ask) tagged with `commonsware` and `android`.
+Be sure to include source code and stack traces if you are encountering crashes.
+
+If you have encountered what is clearly a bug, or a feature request,
+please post an [issue](https://github.com/commonsguy/empub/issues).
+Be certain to include complete steps for reproducing the issue.
+
+Do not ask for help via Twitter.
+
+Also, if you plan on hacking
+on the code with an eye for contributing something back,
+please open an issue that we can use for discussing
+implementation details. Just lobbing a pull request over
+the fence may work, but it may not.
+
+Who Made This?
+--------------
+<a href="http://commonsware.com">![CommonsWare](http://commonsware.com/images/logo.png)</a>
+
+Release Notes
+-------------
+- v0.1.0: initial release
+
View
2 demo/AndroidManifest.xml
@@ -26,6 +26,8 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
+ <activity android:name="com.commonsware.empub.SimpleContentActivity" />
+ <activity android:name="com.commonsware.empub.Preferences"/>
</application>
</manifest>
View
BIN libs/CWAC-LoaderEx.jar
Binary file not shown.
View
40 proguard.cfg
@@ -1,40 +0,0 @@
--optimizationpasses 5
--dontusemixedcaseclassnames
--dontskipnonpubliclibraryclasses
--dontpreverify
--verbose
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Application
--keep public class * extends android.app.Service
--keep public class * extends android.content.BroadcastReceiver
--keep public class * extends android.content.ContentProvider
--keep public class * extends android.app.backup.BackupAgentHelper
--keep public class * extends android.preference.Preference
--keep public class com.android.vending.licensing.ILicensingService
-
--keepclasseswithmembernames class * {
- native <methods>;
-}
-
--keepclasseswithmembers class * {
- public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keepclasseswithmembers class * {
- public <init>(android.content.Context, android.util.AttributeSet, int);
-}
-
--keepclassmembers class * extends android.app.Activity {
- public void *(android.view.View);
-}
-
--keepclassmembers enum * {
- public static **[] values();
- public static ** valueOf(java.lang.String);
-}
-
--keep class * implements android.os.Parcelable {
- public static final android.os.Parcelable$Creator *;
-}
View
3 project.properties
@@ -9,6 +9,5 @@
# Project target.
target=android-14
-android.library.reference.1=../CWAC/LoaderEx
android.library=true
-android.library.reference.2=../3rdParty/ActionBarSherlock-4.0.1/library
+android.library.reference.1=../3rdParty/ActionBarSherlock
View
5 res/layout/empub_image.xml
@@ -0,0 +1,5 @@
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#FFFFFFFF"/>
View
87 res/layout/preference_widget_seekbar.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Layout for a Preference in a PreferenceActivity. The
+ Preference is able to place a specific widget for its particular
+ type in the "widget_frame" layout. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:paddingRight="?android:attr/scrollbarSize">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:minWidth="@dimen/preference_icon_minWidth"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:minWidth="48dp"
+ />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="8dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1">
+
+ <TextView android:id="@+android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ <TextView android:id="@+android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignLeft="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="4" />
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@+android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_below="@android:id/summary"
+ android:layout_alignLeft="@android:id/title"
+ android:minWidth="@dimen/preference_widget_width"
+ android:gravity="center"
+ android:orientation="vertical" />
+
+ <SeekBar android:id="@+id/seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/summary"
+ android:layout_toRightOf="@android:id/widget_frame"
+ android:layout_alignParentRight="true" />
+
+ </RelativeLayout>
+
+</LinearLayout>
View
9 res/menu/empub_actions.xml
@@ -1,9 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item
- android:id="@+id/empub_zoom"
- android:actionLayout="@layout/empub_zoom"
- android:showAsAction="ifRoom">
- </item>
-
-</menu>
View
24 res/menu/empub_options.xml
@@ -0,0 +1,24 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/empub_settings"
+ android:title="@string/empub_settings"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:showAsAction="never">
+ </item>
+
+ <item
+ android:id="@+id/empub_help"
+ android:title="@string/empub_help"
+ android:icon="@android:drawable/ic_menu_help"
+ android:showAsAction="never">
+ </item>
+
+ <item
+ android:id="@+id/empub_about"
+ android:title="@string/empub_about"
+ android:icon="@android:drawable/ic_menu_info_details"
+ android:showAsAction="never">
+ </item>
+
+</menu>
View
6 res/values-land/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+
+ <!-- Preference widget area width (to the left of the text) -->
+ <dimen name="preference_widget_width">72dp</dimen>
+
+</resources>
View
6 res/values-large/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+
+ <!-- Preference widget area width (to the left of the text) -->
+ <dimen name="preference_widget_width">56dp</dimen>
+
+</resources>
View
6 res/values-sw600dp-w1280dp/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+
+ <!-- Preference widget area width (to the left of the text) -->
+ <dimen name="preference_widget_width">64dp</dimen>
+
+</resources>
View
10 res/values-w720dp/dimens.xml
@@ -0,0 +1,10 @@
+<resources>
+
+ <!--
+ Minimum space to allocate to the left of a preference item for an icon.
+ This helps in aligning titles when some items have icons and some don't. When space is
+ at a premium, we don't pre-allocate any space.
+ -->
+ <dimen name="preference_icon_minWidth">56dp</dimen>
+
+</resources>
View
12 res/values/dimens.xml
@@ -0,0 +1,12 @@
+<resources>
+
+ <!-- Preference widget area width (to the left of the text) -->
+ <dimen name="preference_widget_width">48dp</dimen>
+ <!--
+ Minimum space to allocate to the left of a preference item for an icon.
+ This helps in aligning titles when some items have icons and some don't. When space is
+ at a premium, we don't pre-allocate any space.
+ -->
+ <dimen name="preference_icon_minWidth">0dp</dimen>
+
+</resources>
View
11 res/values/strings.xml
@@ -1,8 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="app_name">EmPub Reader</string>
<string name="empub_exception_json">Exception loading book contents JSON</string>
<string name="empub_toc">Table of Contents</string>
<string name="empub_zoom_caption">Zoom:</string>
+ <string name="empub_about">About</string>
+ <string name="empub_help">Help</string>
+ <string name="empub_cover">Cover</string>
+ <string name="empub_preftitle">Display &amp; Navigation</string>
+ <string name="empub_prefdesc">Settings for use of EmPub</string>
+ <string name="empub_settings">Settings</string>
+ <string name="empub_lastpositiontitle">Save Last Position</string>
+ <string name="empub_lastpositionsummary">Save the last chapter you were viewing and open up on that chapter when re-opening the app</string>
+ <string name="empub_zoomtitle">Text Zoom Level</string>
+ <string name="empub_zoomsummary">Size of font as percentage of normal (25-200%)</string>
</resources>
View
9 res/values/styles.xml
@@ -0,0 +1,9 @@
+<resources>
+
+ <declare-styleable name="ProgressBar">
+
+ <!-- Defines the maximum value the progress can take. -->
+ <attr name="max" format="integer"/>
+ </declare-styleable>
+
+</resources>
View
17 res/xml/pref_display.xml
@@ -0,0 +1,17 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:empub="http://schemas.android.com/apk/res-auto">
+
+ <com.commonsware.empub.SeekBarPreference
+ android:defaultValue="100"
+ android:key="zoom"
+ empub:max="175"
+ android:summary="@string/empub_zoomsummary"
+ android:title="@string/empub_zoomtitle"/>
+
+ <CheckBoxPreference
+ android:defaultValue="true"
+ android:key="saveLastPosition"
+ android:summary="@string/empub_lastpositionsummary"
+ android:title="@string/empub_lastpositiontitle"/>
+
+</PreferenceScreen>
View
12 res/xml/preference_headers.xml
@@ -0,0 +1,12 @@
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <header
+ android:fragment="com.commonsware.empub.StockPreferenceFragment"
+ android:summary="@string/empub_prefdesc"
+ android:title="@string/empub_preftitle">
+ <extra
+ android:name="resource"
+ android:value="pref_display"/>
+ </header>
+
+</preference-headers>
View
21 src/com/commonsware/empub/BookContents.java
@@ -1,3 +1,14 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
package com.commonsware.empub;
import java.util.HashMap;
@@ -40,10 +51,18 @@ String getChapterTitle(int position) {
}
int getPositionForFile(String file) {
- return(files.get(file));
+ return(files.get(file.substring(5)));
}
String getTOCFile() {
return(raw.optString("toc"));
}
+
+ String getCoverImage() {
+ return(raw.optString("cover"));
+ }
+
+ String getTitle() {
+ return(raw.optString("title"));
+ }
}
View
186 src/com/commonsware/empub/ChapterFragment.java
@@ -1,31 +1,27 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
package com.commonsware.empub;
-import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
-import android.widget.SeekBar;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuInflater;
-import com.commonsware.cwac.loaderex.acl.SharedPreferencesLoader;
-
-public class ChapterFragment extends WebViewFragment implements
- SeekBar.OnSeekBarChangeListener,
- SharedPreferences.OnSharedPreferenceChangeListener {
- private static int cacheZoomLevel=100;
+
+public class ChapterFragment extends ContentFragment {
private static final String KEY_FILE="file";
- private static final String PREF_ZOOM="zoom";
- private ChapterClient client=null;
- private NavListener nav=null;
- private SeekBar zoom=null;
- private SharedPreferences prefs=null;
+ private int zoomLevel=100;
- static ChapterFragment newInstance(String file) {
+ protected static ChapterFragment newInstance(String file) {
ChapterFragment f=new ChapterFragment();
Bundle args=new Bundle();
@@ -35,164 +31,82 @@ static ChapterFragment newInstance(String file) {
return(f);
}
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setRetainInstance(true);
- setHasOptionsMenu(true);
- prefs=((EmPubActivity)getActivity()).getPreferences();
- this.client=new ChapterClient();
- }
@Override
- public View onCreateView(LayoutInflater inflater,
- ViewGroup container,
- Bundle savedInstanceState) {
- View result=
- super.onCreateView(inflater, container, savedInstanceState);
-
- setZoom();
- getWebView().setWebViewClient(client);
-
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
// following required due to bug
// http://code.google.com/p/android/issues/detail?id=3440
getWebView().getSettings().setBuiltInZoomControls(false);
- getWebView().getSettings().setJavaScriptEnabled(true);
+ getWebView().setWebViewClient(new ChapterClient());
+ updateZoom();
- prefs.registerOnSharedPreferenceChangeListener(this);
- cacheZoomLevel=prefs.getInt(PREF_ZOOM, 100);
+ final String anchor=
+ ((EmPubActivity)getActivity()).popAnchor(getArguments().getString(KEY_FILE));
- if (zoom != null) {
- updateZoom();
- }
+ // would use onPageFinished(), but it is hopelessly
+ // buggy
- String page=
- "file:///android_asset/" + getArguments().getString(KEY_FILE);
-
- getWebView().loadUrl(page);
-
- final String anchor=((EmPubActivity)getActivity()).popAnchor(getArguments().getString(KEY_FILE));
-
- // would use onPageFinished(), but it is hopelessly buggy
-
- if (anchor!=null) {
- result.postDelayed(new Runnable() {
+ if (anchor != null) {
+ getWebView().postDelayed(new Runnable() {
public void run() {
jumpTo(anchor);
}
}, 1000);
}
-
- return(result);
}
-
+
@Override
public void onResume() {
super.onResume();
-
- setZoom();
- }
-
- @Override
- public void onDestroy() {
- prefs.unregisterOnSharedPreferenceChangeListener(this);
-
- super.onDestroy();
- }
-
- // needed due to Android Support bug
- // see http://stackoverflow.com/questions/8748064/starting-activity-from-fragment-causes-nullpointerexception
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- setUserVisibleHint(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- inflater.inflate(R.menu.empub_actions, menu);
-
- View action=menu.findItem(R.id.empub_zoom).getActionView();
-
- zoom=(SeekBar)action.findViewById(R.id.zoomBar);
- zoom.setOnSeekBarChangeListener(this);
-
- if (prefs != null && getWebView() != null) {
- updateZoom();
- }
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- if (fromUser) {
- cacheZoomLevel=progress + 50;
- SharedPreferencesLoader.persist(prefs.edit()
- .putInt(PREF_ZOOM,
- progress + 50));
- setZoom();
- }
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // unused
+
+ setZoom(((EmPubActivity)getActivity()).getZoom());
}
@Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // unused
+ String getPage() {
+ return("file:///android_asset/book/" + getArguments().getString(KEY_FILE));
}
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
- String key) {
+ protected void jumpTo(String anchor) {
if (getWebView() != null) {
- setZoom();
- }
- }
+ StringBuilder buf=
+ new StringBuilder("javascript:location.href=\"#");
- void setNavListener(NavListener nav) {
- this.nav=nav;
- }
-
- void jumpTo(String anchor) {
- if (getWebView()!=null) {
- StringBuilder buf=new StringBuilder("javascript:location.href=\"#");
-
buf.append(anchor);
buf.append("\";");
-
+
getWebView().loadUrl(buf.toString());
}
}
- private void updateZoom() {
- setZoom();
- zoom.setProgress(cacheZoomLevel - 50);
+ void setZoom(int zoomLevel) {
+ this.zoomLevel=zoomLevel;
+
+ if (getWebView()!=null) {
+ updateZoom();
+ }
}
-
- private void setZoom() {
+
+ private void updateZoom() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- getWebView().getSettings().setTextZoom(cacheZoomLevel);
+ getWebView().getSettings().setTextZoom(zoomLevel);
}
else {
- if (cacheZoomLevel <= 25) {
+ if (zoomLevel <= 25) {
getWebView().getSettings()
.setTextSize(WebSettings.TextSize.SMALLEST);
}
- else if (cacheZoomLevel <= 75) {
+ else if (zoomLevel <= 75) {
getWebView().getSettings()
.setTextSize(WebSettings.TextSize.SMALLER);
}
- else if (cacheZoomLevel <= 125) {
+ else if (zoomLevel <= 125) {
getWebView().getSettings()
.setTextSize(WebSettings.TextSize.NORMAL);
}
- else if (cacheZoomLevel <= 175) {
+ else if (zoomLevel <= 175) {
getWebView().getSettings()
.setTextSize(WebSettings.TextSize.LARGER);
}
@@ -207,10 +121,10 @@ else if (cacheZoomLevel <= 175) {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(EmPubActivity.CONTENT_PREFIX)) {
- nav.onInternalLinkClicked(url);
+ ((NavListener)getActivity()).onInternalLinkClicked(url);
}
else {
- nav.onExternalLinkClicked(url);
+ ((NavListener)getActivity()).onExternalLinkClicked(url);
}
return(true);
View
48 src/com/commonsware/empub/ContentFragment.java
@@ -0,0 +1,48 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+abstract public class ContentFragment extends WebViewFragment {
+ abstract String getPage();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setRetainInstance(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ ViewGroup container,
+ Bundle savedInstanceState) {
+ View result=
+ super.onCreateView(inflater, container, savedInstanceState);
+
+ getWebView().getSettings().setJavaScriptEnabled(true);
+
+ getWebView().loadUrl(getPage());
+
+ return(result);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ setUserVisibleHint(true);
+ }
+}
View
78 src/com/commonsware/empub/ContentsAdapter.java
@@ -0,0 +1,78 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.ViewPager;
+
+class ContentsAdapter extends FragmentStatePagerAdapter {
+ BookContents contents=null;
+ FragmentActivity ctxt=null;
+
+ public ContentsAdapter(FragmentActivity ctxt, BookContents contents) {
+ super(ctxt.getSupportFragmentManager());
+ this.ctxt=ctxt;
+ this.contents=contents;
+ }
+
+ @Override
+ public int getCount() {
+ return(contents.getChapterCount() + 2);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ Fragment frag=null;
+
+ if (position == 0) {
+ frag=
+ ImageFragment.newInstance(contents.getCoverImage(),
+ contents.getTitle());
+ }
+ else if (position == 1) {
+ frag=ChapterFragment.newInstance(contents.getTOCFile());
+ }
+ else {
+ String path=contents.getChapterFile(position - 2);
+
+ frag=ChapterFragment.newInstance(path);
+ }
+
+ return(frag);
+ }
+
+ @Override
+ public String getPageTitle(int position) {
+ if (position == 0) {
+ return(ctxt.getString(R.string.empub_cover));
+ }
+ else if (position == 1) {
+ return(ctxt.getString(R.string.empub_toc));
+ }
+
+ return(contents.getChapterTitle(position - 2));
+ }
+
+ // nasty nasty hack
+ // http://stackoverflow.com/a/9293207/115145
+
+ Fragment getActiveFragment(ViewPager container, int position) {
+ String name=makeFragmentName(container.getId(), position);
+ return ctxt.getSupportFragmentManager().findFragmentByTag(name);
+ }
+
+ private static String makeFragmentName(int viewId, int index) {
+ return "android:switcher:" + viewId + ":" + index;
+ }
+}
View
51 src/com/commonsware/empub/ContentsLoader.java
@@ -1,51 +0,0 @@
-package com.commonsware.empub;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import android.content.Context;
-import android.support.v4.content.AsyncTaskLoader;
-import org.json.JSONObject;
-
-public class ContentsLoader extends AsyncTaskLoader<BookContents> {
- private BookContents contents=null;
-
- public ContentsLoader(Context context) {
- super(context);
- }
-
- @Override
- public BookContents loadInBackground() {
- try {
- StringBuilder buf=new StringBuilder();
- InputStream json=
- getContext().getResources().getAssets().open("contents.json");
- BufferedReader in=new BufferedReader(new InputStreamReader(json));
- String str;
-
- while ((str=in.readLine()) != null) {
- buf.append(str);
- }
-
- in.close();
-
- return(new BookContents(new JSONObject(buf.toString())));
- }
- catch (Exception e) {
- String msg=getContext().getString(R.string.empub_exception_json);
-
- throw new RuntimeException(msg, e);
- }
- }
-
- @Override
- protected void onStartLoading() {
- if (contents != null) {
- deliverResult(contents);
- }
-
- if (takeContentChanged() || contents == null) {
- forceLoad();
- }
- }
-}
View
205 src/com/commonsware/empub/EmPubActivity.java
@@ -1,31 +1,41 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
package com.commonsware.empub;
import java.util.HashMap;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.app.LoaderManager;
-import android.support.v4.content.Loader;
import android.support.v4.view.ViewPager;
import android.view.View;
import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.commonsware.cwac.loaderex.acl.SharedPreferencesLoader;
public class EmPubActivity extends SherlockFragmentActivity implements
- LoaderManager.LoaderCallbacks<BookContents>, NavListener {
+ NavListener {
public static final String TAG="EmPub";
public static final String CONTENT_PREFIX="file:///android_asset/";
public static final String EXTRA_FILE="file";
- private static final int LOADER_CONTENTS=0;
- private static final int LOADER_PREFS=1;
+ private static final String PREF_SAVE_LAST_POSITION=
+ "saveLastPosition";
+ private static final String PREF_LAST_POSITION="lastPosition";
+ static final String PREF_ZOOM="zoom";
+ private static final String MODEL="model";
private ViewPager pager=null;
private BookContents contents=null;
private ContentsAdapter adapter=null;
@@ -36,46 +46,62 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
- ApplicationInfo appInfo=getApplicationInfo();
- int appFlags=appInfo.flags;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD
+ && BuildConfig.DEBUG) {
+ enableStrictMode();
+ }
- if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- enableStrictMode();
- }
+ if (savedInstanceState == null) {
+ getSupportFragmentManager().beginTransaction()
+ .add(new ModelFragment(), MODEL)
+ .commit();
}
setContentView(R.layout.empub_main);
pager=(ViewPager)findViewById(R.id.pager);
-
- getSupportLoaderManager().initLoader(LOADER_PREFS, null,
- new PrefsLoaderCallbacks());
- getSupportLoaderManager().initLoader(LOADER_CONTENTS, null, this);
}
@Override
- public Loader<BookContents> onCreateLoader(int id, Bundle args) {
- return(new ContentsLoader(this));
- }
+ public void onPause() {
+ int position=pager.getCurrentItem();
- @Override
- public void onLoadFinished(Loader<BookContents> loader,
- BookContents contents) {
- if (this.contents == null) {
- this.contents=contents;
- setupPager();
- }
+ SharedPreferencesLoader.persist(prefs.edit()
+ .putInt(PREF_LAST_POSITION,
+ position));
+
+ super.onPause();
}
@Override
- public void onLoaderReset(Loader<BookContents> loader) {
- // unused
+ public boolean onCreateOptionsMenu(Menu menu) {
+ new MenuInflater(this).inflate(R.menu.empub_options, menu);
+
+ return(super.onCreateOptionsMenu(menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
- pager.setCurrentItem(0, false);
+ pager.setCurrentItem(1, false);
+ }
+ else if (item.getItemId() == R.id.empub_settings) {
+ startActivity(new Intent(this, Preferences.class));
+ }
+ else if (item.getItemId() == R.id.empub_about) {
+ Intent i=new Intent(this, SimpleContentActivity.class);
+
+ i.putExtra(SimpleContentActivity.KEY_FILE,
+ "file:///android_asset/misc/about.html");
+
+ startActivity(i);
+ }
+ else if (item.getItemId() == R.id.empub_help) {
+ Intent i=new Intent(this, SimpleContentActivity.class);
+
+ i.putExtra(SimpleContentActivity.KEY_FILE,
+ "file:///android_asset/misc/help.html");
+
+ startActivity(i);
}
return(super.onOptionsItemSelected(item));
@@ -87,16 +113,18 @@ public void onInternalLinkClicked(String url) {
int position=contents.getPositionForFile(pieces[0]);
if (pieces.length == 2) {
- anchors.put(pieces[0], pieces[1]);
+ anchors.put(pieces[0].substring(5), pieces[1]);
- ChapterFragment frag=(ChapterFragment)adapter.getActiveFragment(pager, position+1);
-
- if (frag!=null) {
+ ChapterFragment frag=
+ (ChapterFragment)adapter.getActiveFragment(pager,
+ position + 2);
+
+ if (frag != null) {
frag.jumpTo(pieces[1]);
}
}
- pager.setCurrentItem(position + 1, false);
+ pager.setCurrentItem(position + 2, false);
}
@Override
@@ -107,18 +135,24 @@ public void onExternalLinkClicked(String url) {
String popAnchor(String path) {
return(anchors.remove(path));
}
-
- SharedPreferences getPreferences() {
- return(prefs);
+
+ int getZoom() {
+ return(prefs.getInt(EmPubActivity.PREF_ZOOM, 100));
}
- private void setupPager() {
- if (contents != null && prefs != null) {
- adapter=new ContentsAdapter(this, contents, this);
- pager.setAdapter(adapter);
- findViewById(R.id.progressBar).setVisibility(View.GONE);
- findViewById(R.id.pager).setVisibility(View.VISIBLE);
+ void setupPager(SharedPreferences prefs, BookContents contents) {
+ this.prefs=prefs;
+ this.contents=contents;
+
+ adapter=new ContentsAdapter(this, contents);
+ pager.setAdapter(adapter);
+
+ if (prefs.getBoolean(PREF_SAVE_LAST_POSITION, true)) {
+ pager.setCurrentItem(prefs.getInt(PREF_LAST_POSITION, 0));
}
+
+ findViewById(R.id.progressBar).setVisibility(View.GONE);
+ findViewById(R.id.pager).setVisibility(View.VISIBLE);
}
private void enableStrictMode() {
@@ -129,83 +163,4 @@ private void enableStrictMode() {
.penaltyLog()
.build());
}
-
- private static class ContentsAdapter extends FragmentPagerAdapter {
- BookContents contents=null;
- NavListener nav=null;
- FragmentActivity ctxt=null;
-
- public ContentsAdapter(FragmentActivity ctxt,
- BookContents contents, NavListener nav) {
- super(ctxt.getSupportFragmentManager());
- this.ctxt=ctxt;
- this.contents=contents;
- this.nav=nav;
- }
-
- @Override
- public int getCount() {
- return(contents.getChapterCount() + 1);
- }
-
- @Override
- public Fragment getItem(int position) {
- ChapterFragment frag=null;
-
- if (position == 0) {
- frag=ChapterFragment.newInstance(contents.getTOCFile());
- }
- else {
- String path=contents.getChapterFile(position - 1);
-
- frag=ChapterFragment.newInstance(path);
- }
-
- frag.setNavListener(nav);
-
- return(frag);
- }
-
- @Override
- public String getPageTitle(int position) {
- if (position == 0) {
- return(ctxt.getString(R.string.empub_toc));
- }
-
- return(contents.getChapterTitle(position - 1));
- }
-
- // nasty nasty hack
- // http://stackoverflow.com/a/9293207/115145
-
- Fragment getActiveFragment(ViewPager container, int position) {
- String name=makeFragmentName(container.getId(), position);
- return ctxt.getSupportFragmentManager().findFragmentByTag(name);
- }
-
- private static String makeFragmentName(int viewId, int index) {
- return "android:switcher:" + viewId + ":" + index;
- }
- }
-
- private class PrefsLoaderCallbacks implements
- LoaderManager.LoaderCallbacks<SharedPreferences> {
-
- @Override
- public Loader<SharedPreferences> onCreateLoader(int id, Bundle arg1) {
- return(new SharedPreferencesLoader(EmPubActivity.this));
- }
-
- @Override
- public void onLoadFinished(Loader<SharedPreferences> loader,
- SharedPreferences prefs) {
- EmPubActivity.this.prefs=prefs;
- setupPager();
- }
-
- @Override
- public void onLoaderReset(Loader<SharedPreferences> loader) {
- // unused
- }
- }
}
View
84 src/com/commonsware/empub/ImageFragment.java
@@ -0,0 +1,84 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import java.io.IOException;
+import java.io.InputStream;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import com.actionbarsherlock.app.SherlockFragment;
+
+public class ImageFragment extends SherlockFragment {
+ private static final String KEY_IMAGE="image";
+ private static final String KEY_DESCRIPTION="desc";
+
+ protected static ImageFragment newInstance(String file, String desc) {
+ ImageFragment f=new ImageFragment();
+
+ Bundle args=new Bundle();
+
+ args.putString(KEY_IMAGE, file);
+ args.putString(KEY_DESCRIPTION, desc);
+ f.setArguments(args);
+
+ return(f);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ ViewGroup container,
+ Bundle savedInstanceState) {
+ View contents=
+ inflater.inflate(R.layout.empub_image, container, false);
+ ImageView image=(ImageView)contents.findViewById(R.id.image);
+
+ try {
+ image.setImageBitmap(getImageBitmap());
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Exception loading bitmap", e);
+ }
+
+ image.setContentDescription(getDescription());
+
+ return(contents);
+ }
+
+ private Bitmap getImageBitmap() throws IOException {
+ Bitmap bitmap=null;
+ InputStream is=null;
+
+ try {
+ is=
+ getActivity().getAssets()
+ .open("book/"
+ + getArguments().getString(KEY_IMAGE));
+ bitmap=BitmapFactory.decodeStream(is);
+ }
+ finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+
+ return(bitmap);
+ }
+
+ private String getDescription() {
+ return(getArguments().getString(KEY_DESCRIPTION));
+ }
+}
View
132 src/com/commonsware/empub/ModelFragment.java
@@ -0,0 +1,132 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import com.actionbarsherlock.app.SherlockFragment;
+import org.json.JSONObject;
+
+public class ModelFragment extends SherlockFragment {
+ private SharedPreferences prefs=null;
+ private BookContents contents=null;
+ private PrefsLoadTask prefsTask=null;
+ private ContentsLoadTask contentsTask=null;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ setRetainInstance(true);
+ deliverModel();
+ }
+
+ synchronized private void deliverModel() {
+ if (prefs != null && contents != null) {
+ ((EmPubActivity)getActivity()).setupPager(prefs, contents);
+ }
+ else {
+ if (prefs == null && prefsTask == null) {
+ prefsTask=new PrefsLoadTask();
+ executeAsyncTask(prefsTask,
+ getActivity().getApplicationContext());
+ }
+
+ if (contents == null && contentsTask == null) {
+ contentsTask=new ContentsLoadTask();
+ executeAsyncTask(contentsTask,
+ getActivity().getApplicationContext());
+ }
+ }
+ }
+
+ static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task,
+ T... params) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
+ }
+ else {
+ task.execute(params);
+ }
+ }
+
+ private class PrefsLoadTask extends AsyncTask<Context, Void, Void> {
+ SharedPreferences localPrefs=null;
+
+ @Override
+ protected Void doInBackground(Context... ctxt) {
+ localPrefs=PreferenceManager.getDefaultSharedPreferences(ctxt[0]);
+ localPrefs.getAll();
+
+ return(null);
+ }
+
+ @Override
+ public void onPostExecute(Void arg0) {
+ ModelFragment.this.prefs=localPrefs;
+ ModelFragment.this.prefsTask=null;
+ deliverModel();
+ }
+ }
+
+ private class ContentsLoadTask extends AsyncTask<Context, Void, Void> {
+ private BookContents localContents=null;
+ private Exception e=null;
+
+ @Override
+ protected Void doInBackground(Context... ctxt) {
+ try {
+ StringBuilder buf=new StringBuilder();
+ InputStream json=
+ ctxt[0].getResources().getAssets()
+ .open("book/contents.json");
+ BufferedReader in=
+ new BufferedReader(new InputStreamReader(json));
+ String str;
+
+ while ((str=in.readLine()) != null) {
+ buf.append(str);
+ }
+
+ in.close();
+
+ localContents=new BookContents(new JSONObject(buf.toString()));
+ }
+ catch (Exception e) {
+ this.e=e;
+ }
+
+ return(null);
+ }
+
+ @Override
+ public void onPostExecute(Void arg0) {
+ if (e == null) {
+ ModelFragment.this.contents=localContents;
+ ModelFragment.this.contentsTask=null;
+ deliverModel();
+ }
+ else {
+ Log.e(getClass().getSimpleName(), "Exception loading contents",
+ e);
+ }
+ }
+ }
+}
View
11 src/com/commonsware/empub/NavListener.java
@@ -1,3 +1,14 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
package com.commonsware.empub;
public interface NavListener {
View
33 src/com/commonsware/empub/Preferences.java
@@ -0,0 +1,33 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import java.util.List;
+import android.os.Build;
+import android.os.Bundle;
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+public class Preferences extends SherlockPreferenceActivity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (Build.VERSION.SDK_INT<Build.VERSION_CODES.HONEYCOMB) {
+ addPreferencesFromResource(R.xml.pref_display);
+ }
+ }
+
+ @Override
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.preference_headers, target);
+ }
+}
View
249 src/com/commonsware/empub/SeekBarPreference.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.preference.Preference.BaseSavedState;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+/**
+ * @hide
+ */
+public class SeekBarPreference extends Preference
+ implements OnSeekBarChangeListener {
+
+ private int mProgress;
+ private int mMax;
+ private boolean mTrackingTouch;
+
+ public SeekBarPreference(
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.ProgressBar, defStyle, 0);
+ setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
+ a.recycle();
+ setLayoutResource(R.layout.preference_widget_seekbar);
+ }
+
+ public SeekBarPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SeekBarPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ SeekBar seekBar = (SeekBar) view.findViewById(
+ R.id.seekbar);
+ seekBar.setOnSeekBarChangeListener(this);
+ seekBar.setMax(mMax);
+ seekBar.setProgress(mProgress);
+ seekBar.setEnabled(isEnabled());
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return null;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setProgress(restoreValue ? getPersistedInt(mProgress)
+ : (Integer) defaultValue);
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getInt(index, 0);
+ }
+
+// @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (event.getAction() != KeyEvent.ACTION_UP) {
+ if (keyCode == KeyEvent.KEYCODE_PLUS
+ || keyCode == KeyEvent.KEYCODE_EQUALS) {
+ setProgress(getProgress() + 1);
+ return true;
+ }
+ if (keyCode == KeyEvent.KEYCODE_MINUS) {
+ setProgress(getProgress() - 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setMax(int max) {
+ if (max != mMax) {
+ mMax = max;
+ notifyChanged();
+ }
+ }
+
+ public void setProgress(int progress) {
+ setProgress(progress, true);
+ }
+
+ private void setProgress(int progress, boolean notifyChanged) {
+ if (progress > mMax) {
+ progress = mMax;
+ }
+ if (progress < 0) {
+ progress = 0;
+ }
+ if (progress != mProgress) {
+ mProgress = progress;
+ persistInt(progress);
+ if (notifyChanged) {
+ notifyChanged();
+ }
+ }
+ }
+
+ public int getProgress() {
+ return mProgress;
+ }
+
+ /**
+ * Persist the seekBar's progress value if callChangeListener
+ * returns true, otherwise set the seekBar's progress to the stored value
+ */
+ void syncProgress(SeekBar seekBar) {
+ int progress = seekBar.getProgress();
+ if (progress != mProgress) {
+ if (callChangeListener(progress)) {
+ setProgress(progress, false);
+ } else {
+ seekBar.setProgress(mProgress);
+ }
+ }
+ }
+
+ @Override
+ public void onProgressChanged(
+ SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser && !mTrackingTouch) {
+ syncProgress(seekBar);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mTrackingTouch = true;
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mTrackingTouch = false;
+ if (seekBar.getProgress() != mProgress) {
+ syncProgress(seekBar);
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ /*
+ * Suppose a client uses this preference type without persisting. We
+ * must save the instance state so it is able to, for example, survive
+ * orientation changes.
+ */
+
+ final Parcelable superState = super.onSaveInstanceState();
+ if (isPersistent()) {
+ // No need to save instance state since it's persistent
+ return superState;
+ }
+
+ // Save the instance state
+ final SavedState myState = new SavedState(superState);
+ myState.progress = mProgress;
+ myState.max = mMax;
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (!state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ // Restore the instance state
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mProgress = myState.progress;
+ mMax = myState.max;
+ notifyChanged();
+ }
+
+ /**
+ * SavedState, a subclass of {@link BaseSavedState}, will store the state
+ * of MyPreference, a subclass of Preference.
+ * <p>
+ * It is important to always call through to super methods.
+ */
+ private static class SavedState extends BaseSavedState {
+ int progress;
+ int max;
+
+ public SavedState(Parcel source) {
+ super(source);
+
+ // Restore the click counter
+ progress = source.readInt();
+ max = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+
+ // Save the click counter
+ dest.writeInt(progress);
+ dest.writeInt(max);
+ }
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ @SuppressWarnings("unused")
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
View
31 src/com/commonsware/empub/SimpleContentActivity.java
@@ -0,0 +1,31 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.os.Bundle;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
+public class SimpleContentActivity extends SherlockFragmentActivity {
+ public static final String KEY_FILE="file";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ getSupportFragmentManager().beginTransaction()
+ .add(android.R.id.content,
+ SimpleContentFragment.newInstance(getIntent().getStringExtra(KEY_FILE)))
+ .commit();
+ }
+ }
+}
View
34 src/com/commonsware/empub/SimpleContentFragment.java
@@ -0,0 +1,34 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.os.Bundle;
+
+public class SimpleContentFragment extends ContentFragment {
+ private static final String KEY_FILE="file";
+
+ protected static SimpleContentFragment newInstance(String file) {
+ SimpleContentFragment f=new SimpleContentFragment();
+
+ Bundle args=new Bundle();
+
+ args.putString(KEY_FILE, file);
+ f.setArguments(args);
+
+ return(f);
+ }
+
+ @Override
+ String getPage() {
+ return(getArguments().getString(KEY_FILE));
+ }
+}
View
30 src/com/commonsware/empub/StockPreferenceFragment.java
@@ -0,0 +1,30 @@
+/***
+ Copyright (c) 2012 CommonsWare, LLC
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License.
+ */
+
+package com.commonsware.empub;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class StockPreferenceFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ int res=getActivity()
+ .getResources()
+ .getIdentifier(getArguments().getString("resource"),
+ "xml",
+ getActivity().getPackageName());
+
+ addPreferencesFromResource(res);
+ }
+}

0 comments on commit 1bae413

Please sign in to comment.