/* * Copyright (C) 2009-2010 Geometer Plus <contact@geometerplus.com> * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ package org.geometerplus.android.fbreader; import java.util.LinkedList; import android.app.Activity; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Handler; import android.view.View; import android.widget.EpdRender; import android.widget.LinearLayout; import android.widget.TextView; import org.geometerplus.zlibrary.core.application.ZLApplication; import org.geometerplus.zlibrary.core.view.ZLView; import org.geometerplus.zlibrary.text.model.ZLTextModel; import org.geometerplus.zlibrary.text.view.ZLRect; import org.geometerplus.zlibrary.text.view.ZLTextView; import org.geometerplus.zlibrary.ui.android.R; import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication; import org.geometerplus.zlibrary.ui.android.library.ZLAndroidLibrary; import org.geometerplus.zlibrary.ui.android.view.ZLAndroidWidget; abstract class EPDView extends EpdRender implements ZLAndroidLibrary.EventsListener { private final Activity myActivity; private class ViewHandler extends Handler { @Override public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: updateEpdDisplay(); break; case 1: updateEpdRegion((ZLRect)msg.obj); break; case -1: myActivity.finish(); break; } }; }; private final Handler myHandler = new ViewHandler(); public EPDView(Activity activity) { myActivity = activity; } public final Activity getActivity() { return myActivity; } public void repaintEpd() { myHandler.sendEmptyMessage(0); } public void repaintEpdRect(ZLRect rect) { myHandler.sendMessage(myHandler.obtainMessage(1, rect)); } public void finishActivity() { myHandler.sendEmptyMessage(-1); } public interface EventsListener { void onPageScrolling(); void onEpdRepaintFinished(); } private LinkedList<EventsListener> myListeners = new LinkedList<EventsListener>(); public void addEventsListener(EventsListener listener) { myListeners.add(listener); } public void removeEventsListener(EventsListener listener) { myListeners.remove(listener); } protected final void onPageScrolling() { for (EventsListener listener: myListeners) { listener.onPageScrolling(); } } public final void onEpdRepaintFinished() { for (EventsListener listener: myListeners) { listener.onEpdRepaintFinished(); } } public void onResume() { final LinearLayout view = (LinearLayout) myActivity.findViewById(R.id.epd_layout); if (view == null) { throw new RuntimeException("EPDView's activity must be layed out with \"epd_layout\" layout."); } setVdsActive(true); if (getLayout() != view) { bindLayout(view); } myHandler.sendEmptyMessageDelayed(0, 200); } public void onPause() { setVdsActive(false); } @Override public boolean onPageUp(int arg1, int arg2) { final int angle = ZLAndroidApplication.Instance().RotationFlag; scrollPage(angle == ZLAndroidApplication.ROTATE_90 || angle == ZLAndroidApplication.ROTATE_180); return true; } @Override public boolean onPageDown(int arg1, int arg2) { final int angle = ZLAndroidApplication.Instance().RotationFlag; scrollPage(angle == ZLAndroidApplication.ROTATE_0 || angle == ZLAndroidApplication.ROTATE_270); return true; } public final void scrollPage(boolean forward) { final ZLView view = ZLApplication.Instance().getCurrentView(); if (view instanceof ZLTextView) { onPageScrolling(); ((ZLTextView) view).scrollPage(forward, ZLTextView.ScrollingMode.NO_OVERLAPPING, 0); ZLApplication.Instance().repaintView(); } } public void updateEpdDisplay() { updateEpdStatusbar(); updateEpdView(); final View bar = myActivity.findViewById(R.id.statusbar_layout); if (bar.getWidth() != 0 && bar.getHeight() != 0) { final int left = bar.getLeft(); final int top = bar.getTop(); final int right = left + bar.getWidth(); final int bottom = top + bar.getHeight(); final Rect rect = new Rect(left + bar.getPaddingLeft(), top + bar.getPaddingTop(), right + bar.getPaddingRight(), bottom + bar.getPaddingBottom()); partialUpdateEpdView(rect); } } private void updateEpdRegion(ZLRect rect) { final ZLAndroidWidget widget = (ZLAndroidWidget)myActivity.findViewById(R.id.main_view_epd); final Canvas canvas = getEpdCanvas(); widget.draw(canvas); final Rect region = widget.convertRect(rect); final int minLeft = 3; final int maxRight = widget.getWidth() - 4; final int minTop = 3; final int maxBottom = widget.getHeight() - 1; region.left = Math.max(region.left, minLeft); region.top = Math.max(region.top, minTop); region.right = Math.min(region.right, maxRight); region.bottom = Math.min(region.bottom, maxBottom); final int minWidth = 160; if (region.width() < minWidth) { final int dx = (minWidth + 1 - region.width()) / 2; if (region.left < minLeft + dx) { region.right += 2 * dx; } else if (region.right > maxRight - dx) { region.left -= 2 * dx; } else { region.left -= dx; region.right += dx; } } partialUpdateEpdView(region); } private void updateEpdStatusbar() { final TextView statusPositionText = (TextView) myActivity.findViewById(R.id.statusbar_position_text); String positionText = ""; final ZLView view = ZLApplication.Instance().getCurrentView(); if (view instanceof ZLTextView) { ZLTextView textView = (ZLTextView) view; ZLTextModel model = textView.getModel(); if (model != null && model.getParagraphsNumber() != 0) { if (textView.getContext().getWidth() == 0 || textView.getContext().getHeight() == 0) { ((ZLAndroidWidget)myActivity.findViewById(R.id.main_view_epd)).resetContext(); } final int page = textView.computeCurrentPage(); final int pagesNumber = textView.computePageNumber(); positionText = makePositionText(page, pagesNumber); } } statusPositionText.setText(positionText); } public static String makePositionText(int page, int pagesNumber) { return "" + page + " / " + pagesNumber; } }