package com.masterofcode.android.magreader;
import java.util.ArrayList;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SearchView;
import android.widget.Toast;
import com.masterofcode.android.EPubBook.EPubBook;
import com.masterofcode.android.EPubBook.EPubBookProcessingListener;
import com.masterofcode.android.EPubBookRender.EPubBookRender;
import com.masterofcode.android.magreader.bookmarks.BookmarksManager;
import com.masterofcode.android.magreader.utils.ApplicationUtils;
import com.masterofcode.android.magreader.utils.constants.Constants;
import com.sandsmedia.apps.mobile.android.epub.lib.R;
public class EpubViewerActivity extends Activity implements OnGesturePerformedListener {
final public String BUNDLE_KEY_EPUB_FILE_PATH = "epub_file_path";
final public String BUNDLE_KEY_EPUB_READING = "epub_reading";
final public String BUNDLE_KEY_EPUB_TOC_SHOW_STATUS = "epub_toc_show_status";
final public String BUNDLE_KEY_EPUB_BOOKMARKED_TOPICS = "epub_toc_bookmarked_topics"; // topics that bookmarked in current magazine
final public String BUNDLE_KEY_EPUB_FONT_CHANGE_FACTOR = "epub_font_change_factor";
final private int TOC_BASE_ID = 100;
final private int FONT_CHANGE_FACTOR_MIN = -8;
final private int FONT_CHANGE_FACTOR_MAX = 8;
private int EPUB_DOWNLOADING = 1;
private int EPUB_EXTRACTING = 2;
private int EPUB_PROCESSING_MEDIA = 3;
private int EPUB_COPYING = 4;
private int EPUB_HIGHLIGHT_TOPICS = 5;
private int THREAD_PROGRESS = 0;
private int THREAD_FINISH = 1;
String epubUrl;
String epubFilePath;
String epubCoverFilePath;
boolean epubLoaded = false;
EPubBook ePubBook = null;
EPubBookRender ePubBookRender = null;
float msx, msy;
private ProgressDialog bookExtractingProgressDialog = null;
private ProgressDialog bookDownloadProgressDialog = null;
private ProgressDialog bookCopyProgressDialog = null;
private ProgressDialog bookProcessMediaProgressDialog = null;
private ProgressDialog processingProgressDialog = null;
private boolean epubReading = false;
private int topicIndex = 0;
private float topicContentOffset = 0.0f;
private boolean tocIsShowed = false;
private ArrayList<String> topicTitles;
private ArrayList<Integer> bookmarkedTopics = null;
private int previousTopicIndex = -1;
private int fontSizeChangeFactor = 0;
private boolean isHighlightingMode = false;
private String highlightingKeyword = null;
private ArrayList<Integer> highlightingTopics = null;
private boolean isRestored = false;
private ActionBar actionBar;
private GestureLibrary gestureLib;
private GestureOverlayView gestureOverlayView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.epub_view);
gestureOverlayView = new GestureOverlayView(this);
View inflate = getLayoutInflater().inflate(R.layout.epub_view, null);
gestureOverlayView.addView(inflate);
gestureOverlayView.addOnGesturePerformedListener(this);
gestureOverlayView.setGestureColor(Color.TRANSPARENT);
gestureOverlayView.setUncertainGestureColor(Color.TRANSPARENT);
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gestureLib.load()) {
finish();
}
setContentView(gestureOverlayView);
gestureOverlayView.setEventsInterceptionEnabled(true);
gestureOverlayView.setGestureVisible(false);
if (savedInstanceState==null) {
Intent intent = this.getIntent();
epubFilePath = intent.getStringExtra(Constants.BUNDLE_KEY_EPUB_FILE_PATH);
epubCoverFilePath = intent.getStringExtra(Constants.BUNDLE_KEY_EPUB_COVER_FILE_PATH);
topicIndex = intent.getIntExtra(Constants.BUNDLE_KEY_EPUB_TOPIC_INDEX, 0);
topicContentOffset = intent.getFloatExtra(Constants.BUNDLE_KEY_EPUB_TOPIC_CONTENT_OFFSET, 0);
isHighlightingMode = intent.getBooleanExtra(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_MODE, false);
highlightingKeyword = intent.getStringExtra(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_KEYWORD);
highlightingTopics = intent.getIntegerArrayListExtra(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_TOPICS);
} else {
epubReading = savedInstanceState.getBoolean(BUNDLE_KEY_EPUB_READING);
epubCoverFilePath = savedInstanceState.getString(Constants.BUNDLE_KEY_EPUB_COVER_FILE_PATH);
if(epubReading)
{
epubFilePath = savedInstanceState.getString(Constants.BUNDLE_KEY_EPUB_FILE_PATH);
topicIndex = savedInstanceState.getInt(Constants.BUNDLE_KEY_EPUB_TOPIC_INDEX, 0);
topicContentOffset = savedInstanceState.getFloat(Constants.BUNDLE_KEY_EPUB_TOPIC_CONTENT_OFFSET);
tocIsShowed = savedInstanceState.getBoolean(BUNDLE_KEY_EPUB_TOC_SHOW_STATUS);
bookmarkedTopics = savedInstanceState.getIntegerArrayList(BUNDLE_KEY_EPUB_BOOKMARKED_TOPICS);
fontSizeChangeFactor = savedInstanceState.getInt(BUNDLE_KEY_EPUB_FONT_CHANGE_FACTOR, 0);
isRestored = true;
} else {
epubFilePath = savedInstanceState.getString(Constants.BUNDLE_KEY_EPUB_FILE_PATH);
}
isHighlightingMode = savedInstanceState.getBoolean(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_MODE, false);
if(isHighlightingMode)
{
highlightingKeyword = savedInstanceState.getString(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_KEYWORD);
highlightingTopics = savedInstanceState.getIntegerArrayList(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_TOPICS);
}
}
if(isHighlightingMode)
{
if(highlightingKeyword==null || highlightingTopics==null) isHighlightingMode = false;
}
this.actionBar = getActionBar();
loadEpub();
extractEpub();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(epubReading)
{
outState.putInt(Constants.BUNDLE_KEY_EPUB_TOPIC_INDEX, ePubBookRender.getCurrentTopicIndex());
outState.putFloat(Constants.BUNDLE_KEY_EPUB_TOPIC_CONTENT_OFFSET, ePubBookRender.getCurrentTopicContentOffset());
outState.putBoolean(BUNDLE_KEY_EPUB_TOC_SHOW_STATUS, ePubBookRender.isTOCShow());
outState.putInt(BUNDLE_KEY_EPUB_FONT_CHANGE_FACTOR, fontSizeChangeFactor);
}
outState.putBoolean(BUNDLE_KEY_EPUB_READING, epubReading);
outState.putString(Constants.BUNDLE_KEY_EPUB_FILE_PATH, epubFilePath);
outState.putString(Constants.BUNDLE_KEY_EPUB_COVER_FILE_PATH, epubCoverFilePath);
outState.putIntegerArrayList(BUNDLE_KEY_EPUB_BOOKMARKED_TOPICS, bookmarkedTopics);
outState.putBoolean(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_MODE, isHighlightingMode);
if(isHighlightingMode)
{
outState.putString(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_KEYWORD, highlightingKeyword);
outState.putIntegerArrayList(Constants.BUNDLE_KEY_EPUB_HIGHLIGHTING_TOPICS, highlightingTopics);
}
}
private void loadFontChangeFactor()
{
if(epubLoaded)
{
fontSizeChangeFactor = ApplicationUtils.getPrefPropertyInt(this, ePubBook.getBookName()+".font_change_factor");
}
}
private void saveFontChangeFactor()
{
if(epubLoaded)
{
ApplicationUtils.setPrefProperty(this, ePubBook.getBookName()+".font_change_factor", fontSizeChangeFactor);
}
}
public void startReadingEpub()
{
epubReading = true;
ePubBookRender = new EPubBookRender(ePubBook, this, (ViewGroup) findViewById(R.id.renderContainer));
ePubBookRender.setActionBar(actionBar);
ePubBookRender.setRenderController((ViewGroup) findViewById(R.id.renderController));
ePubBookRender.setRenderView((ViewGroup) findViewById(R.id.renderView));
ePubBookRender.setCurrentTopicIndex(topicIndex);
ePubBookRender.setFontChangeFactor(fontSizeChangeFactor);
ePubBookRender.setHighlightMode(isHighlightingMode);
ePubBookRender.setTocEventsHandler(TOCEventsHandler);
if(isHighlightingMode)
{
ePubBookRender.setHighlightningTopics(highlightingTopics);
}
ePubBookRender.render();
ePubBookRender.setCurrentTopicContentOffset(topicContentOffset);
ePubBookRender.setTopicChangeHandler(topicChangeHandler);
if(bookmarkedTopics==null)
bookmarkedTopics = BookmarksManager.GetInstance().queryBookmarkedTopics(ePubBook.getBookName());
if(tocIsShowed)ePubBookRender.showTOC();
// topic titles
ePubBook.loatTopicTitles();
topicTitles = ePubBook.getTopicTitles();
if(topicTitles!=null)
{
this.invalidateOptionsMenu();
}
}
public void extractEpub()
{
if(!ePubBook.isNeedExtract())
{
processEPubMedia();
return;
}
if(bookExtractingProgressDialog==null) bookExtractingProgressDialog = new ProgressDialog(this);
bookExtractingProgressDialog.setCancelable(false);
bookExtractingProgressDialog.setMessage("Extracting...");
bookExtractingProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
bookExtractingProgressDialog.setProgress(0);
bookExtractingProgressDialog.setMax(100);
bookExtractingProgressDialog.show();
Thread background = new Thread (new Runnable() {
public void run() {
ePubBook.extractContentToExternalStorage(new EPubBookProcessingListener() {
@Override
public void onProgress(long percentsExtracted) {
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_EXTRACTING, THREAD_PROGRESS, (int) percentsExtracted));
}
});
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_EXTRACTING, THREAD_FINISH, 0));
}
});
background.start();
}
private void hightlightMagazineTopics()
{
if(!isHighlightingMode)
{
startReadingEpub();
return;
}
if(processingProgressDialog==null) processingProgressDialog = new ProgressDialog(this);
processingProgressDialog.setCancelable(false);
processingProgressDialog.setMessage("Highlight topics keywords...");
processingProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
processingProgressDialog.setProgress(0);
processingProgressDialog.setMax(highlightingTopics.size());
processingProgressDialog.show();
Thread background = new Thread (new Runnable() {
public void run() {
ePubBook.hightlightTopics(highlightingTopics, highlightingKeyword, new EPubBookProcessingListener() {
@Override
public void onProgress(long topicsHighlighted) {
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_HIGHLIGHT_TOPICS, THREAD_PROGRESS, (int) topicsHighlighted));
}
});
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_HIGHLIGHT_TOPICS, THREAD_FINISH, 0));
}
});
background.start();
}
private void processEPubMedia()
{
if(!ePubBook.isNeedProcessingMedia())
{
if(isHighlightingMode && !isRestored)hightlightMagazineTopics();
else startReadingEpub();
return;
}
Log.i("---", "start processing");
if(bookProcessMediaProgressDialog==null) bookProcessMediaProgressDialog = new ProgressDialog(this);
bookProcessMediaProgressDialog.setCancelable(false);
bookProcessMediaProgressDialog.setMessage("Processing media...");
bookProcessMediaProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
bookProcessMediaProgressDialog.setProgress(0);
bookProcessMediaProgressDialog.setMax(100);
bookProcessMediaProgressDialog.show();
Thread background = new Thread (new Runnable() {
public void run() {
ePubBook.processMedia(new EPubBookProcessingListener() {
@Override
public void onProgress(long percentsExtracted) {
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_PROCESSING_MEDIA, THREAD_PROGRESS, (int) percentsExtracted));
}
});
progressHandler.sendMessage(progressHandler.obtainMessage(EPUB_PROCESSING_MEDIA, THREAD_FINISH, 0));
}
});
background.start();
}
public void loadEpub()
{
ePubBook = new EPubBook(this, epubFilePath, true);
try {
ePubBook.load();
epubLoaded = true;
if(topicIndex<0 || topicIndex>=ePubBook.getTopicsCount() ) topicIndex = 0;
loadFontChangeFactor();
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("unused")
private void doFontSizeDecrease()
{
if(fontSizeChangeFactor==FONT_CHANGE_FACTOR_MIN)return;
if(!epubReading)return;
fontSizeChangeFactor--;
ePubBookRender.changeFontWithFactor(fontSizeChangeFactor);
saveFontChangeFactor();
}
@SuppressWarnings("unused")
private void doFontSizeIncrease()
{
if(fontSizeChangeFactor==FONT_CHANGE_FACTOR_MAX)return;
if(!epubReading)return;
fontSizeChangeFactor++;
ePubBookRender.changeFontWithFactor(fontSizeChangeFactor);
saveFontChangeFactor();
}
private boolean isTopicIndexBookmarked(int index)
{
if(bookmarkedTopics!=null)
{
for(int i=0; i<bookmarkedTopics.size(); i++)
{
if(bookmarkedTopics.get(i).intValue()==index) return true;
}
}
return false;
}
private void doBookmark()
{
if(epubReading)
{
int topicIndex = ePubBookRender.getCurrentTopicIndex();
if(!isTopicIndexBookmarked(topicIndex))
{
String topicTitle = null;
if(topicTitles!=null)
{
if(topicIndex>0 && topicIndex<topicTitles.size()) topicTitle = topicTitles.get(topicIndex);
}
String magazineTitle = ePubBook.getTitle();
BookmarksManager.GetInstance().BookmarkMagazine(magazineTitle, ePubBook.getBookName(), epubFilePath, epubCoverFilePath, ePubBookRender.getCurrentTopicFilePath(), topicTitle, topicIndex, ePubBookRender!=null ? ePubBookRender.getCurrentTopicContentOffset() : 0);
Toast.makeText(this, R.string.bookmarks_topic_added, Toast.LENGTH_SHORT).show();
bookmarkedTopics.add(Integer.valueOf(topicIndex));
invalidateOptionsMenu();
}
}
}
private void goToTopicViaTextTOC(int index)
{
if(ePubBookRender!=null) ePubBookRender.goToTopicViaTextTOC(index);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.magazine_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
super.onPrepareOptionsMenu(menu);
// check bookmarking status
MenuItem itemBookmark = menu.findItem(R.id.menu_magazine_bookmark);
if(itemBookmark!=null)
{
if(epubReading)
{
if(ePubBookRender!=null)
{
if(isTopicIndexBookmarked(ePubBookRender.getCurrentTopicIndex()))
{
itemBookmark.setEnabled(false);
itemBookmark.setVisible(false);
} else {
itemBookmark.setEnabled(true);
itemBookmark.setVisible(true);
}
}
}
}
// prepare toc
MenuItem item = menu.findItem(R.id.menu_magazine_toc);
if(item!=null)
{
SubMenu m = item.getSubMenu();
if(m!=null)
{
if(topicTitles!=null)
{
// remove old
ArrayList<Integer> forRemove = new ArrayList<Integer>();
for(int i=0; i<m.size(); i++)
{
MenuItem cur = m.getItem(i);
forRemove.add(Integer.valueOf(cur.getItemId()));
}
for(int i=0; i<forRemove.size(); i++)
{
m.removeItem(forRemove.get(i).intValue());
}
// add new
for(int i=0; i<topicTitles.size(); i++)
{
// MenuItem newItem =
m.add(Menu.NONE, TOC_BASE_ID+i, i, topicTitles.get(i));
// if(i==2)
// {
// newItem.setCheckable(true);
// newItem.setChecked(true);
// }
}
}
}
}
//search
final SearchView searchView = (SearchView) menu.findItem(R.id.menu_magazine_search).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
searchView.setIconified(true);
Intent intent = new Intent(EpubViewerActivity.this, SearchActivity.class);
intent.putExtra(Constants.BUNDLE_KEY_SEARCH_KEYWORD, query);
intent.putExtra(Constants.BUNDLE_KEY_SEARCH_TYPE, Constants.SEARCH_TYPE_LIBRARY);
startActivity(intent);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if(topicTitles!=null)
{
if(itemId>=TOC_BASE_ID && itemId<TOC_BASE_ID + topicTitles.size())
{
goToTopicViaTextTOC(itemId - TOC_BASE_ID);
return true;
}
}
if (itemId == R.id.menu_magazine_bookmark) {
doBookmark();
return true;
} else if (itemId == android.R.id.home) {
finish();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
Handler topicChangeHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what==0)
{
int newTopicIndex = msg.arg1;
// Log.i("===============", "topic changed="+newTopicIndex);
if(previousTopicIndex==-1)
{
invalidateOptionsMenu(); // there is no previous topic
} else {
if(isTopicIndexBookmarked(previousTopicIndex)!=isTopicIndexBookmarked(newTopicIndex))
invalidateOptionsMenu();
}
previousTopicIndex = newTopicIndex;
} else if(msg.what==1)
{
invalidateOptionsMenu();
}
}
};
Handler TOCEventsHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what==EPubBookRender.TOC_EVENT_SHOW)
{
gestureOverlayView.setEventsInterceptionEnabled(false);
} else if(msg.what==EPubBookRender.TOC_EVENT_HIDE)
{
gestureOverlayView.setEventsInterceptionEnabled(true);
}
}
};
/*
Handler renderEventsHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what==0)
{
}
}
};
*/
Handler progressHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what==EPUB_EXTRACTING)
{
if(msg.arg1==THREAD_PROGRESS)
{
bookExtractingProgressDialog.setProgress(msg.arg2);
} else if (msg.arg1==THREAD_FINISH) {
bookExtractingProgressDialog.dismiss();
processEPubMedia();
}
} else if (msg.what==EPUB_DOWNLOADING){
if(msg.arg1==THREAD_FINISH) {
bookDownloadProgressDialog.dismiss();
loadEpub();
extractEpub();
}
} else if (msg.what==EPUB_PROCESSING_MEDIA){
if(msg.arg1==THREAD_FINISH)
{
bookProcessMediaProgressDialog.dismiss();
if(isHighlightingMode)hightlightMagazineTopics();
else startReadingEpub();
} else {
bookProcessMediaProgressDialog.setProgress(msg.arg2);
}
} else if (msg.what==EPUB_COPYING){
if(msg.arg1==THREAD_FINISH) {
bookCopyProgressDialog.dismiss();
loadEpub();
extractEpub();
}
} else if (msg.what==EPUB_HIGHLIGHT_TOPICS){
if(msg.arg1==THREAD_FINISH) {
processingProgressDialog.dismiss();
startReadingEpub();
} else {
processingProgressDialog.setProgress(msg.arg2);
}
}
}
};
public void openLink(String url) {
DialogFragment newFragment = OpenExternalLinkDialogFragment.newInstance(R.string.magazine_open_link_question_subtitle, url, this);
newFragment.show(getFragmentManager(), "dialog");
}
public void openExternalLink(String url) {
try{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} catch (Exception e)
{
}
}
public static class OpenExternalLinkDialogFragment extends DialogFragment {
public static OpenExternalLinkDialogFragment newInstance(int title, String url, Activity context) {
OpenExternalLinkDialogFragment frag = new OpenExternalLinkDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
args.putString("url", url);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
final String url = getArguments().getString("url");
return new AlertDialog.Builder(getActivity())
.setTitle(title)
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
((EpubViewerActivity)getActivity()).openExternalLink(url);
}
}
)
.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}
)
.create();
}
}
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture)
{
if(ePubBookRender!=null)
{
if(ePubBookRender.isTOCShow())return;
}
ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
if(predictions!=null)
{
for (Prediction prediction : predictions) {
if (prediction.score > 1.0) {
if(prediction.name.equalsIgnoreCase("prev_topic"))
{
if(ePubBookRender!=null)ePubBookRender.loadPrevTopic();
break;
}
else if(prediction.name.equalsIgnoreCase("next_topic"))
{
if(ePubBookRender!=null)ePubBookRender.loadNextTopic();
break;
}
}
}
}
}
}