diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0ee2fadd2..c9e85df04 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,5 +1,5 @@ - + @@ -75,7 +75,7 @@ - + diff --git a/AndroidManifest.xml.pattern b/AndroidManifest.xml.pattern index 9c61809c5..b86275398 100644 --- a/AndroidManifest.xml.pattern +++ b/AndroidManifest.xml.pattern @@ -75,7 +75,7 @@ - + diff --git a/ChangeLog b/ChangeLog index 0831653ce..1ee56197b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ -===== 0.99.11 (??? ??, 2011) ===== +===== 0.99.11 (Feb 01, 2011) ===== * Galician translation has been added (by Miguel Anxo Bouzada) +* Czech translation has been updated (by Marek Pavelka) +* Mobipocket images/cover/links support has been added (by Steffen Siebert) +* Small fixes ===== 0.99.10 (Jan 30, 2011) ===== * Full-size image view diff --git a/VERSION b/VERSION index a041fc3d2..d26847487 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.99.10 +0.99.11 diff --git a/assets/resources/application/cs.xml b/assets/resources/application/cs.xml index bec853217..8da55fbd9 100644 --- a/assets/resources/application/cs.xml +++ b/assets/resources/application/cs.xml @@ -137,8 +137,8 @@ - - + + @@ -158,9 +158,9 @@ - - - + + + diff --git a/assets/resources/zlibrary/cs.xml b/assets/resources/zlibrary/cs.xml index dec168d5d..1151cc234 100644 --- a/assets/resources/zlibrary/cs.xml +++ b/assets/resources/zlibrary/cs.xml @@ -13,7 +13,7 @@ - + diff --git a/src/org/geometerplus/android/fbreader/BookInfoActivity.java b/src/org/geometerplus/android/fbreader/BookInfoActivity.java index bf0a7e9cf..0c67650d5 100644 --- a/src/org/geometerplus/android/fbreader/BookInfoActivity.java +++ b/src/org/geometerplus/android/fbreader/BookInfoActivity.java @@ -59,8 +59,8 @@ public class BookInfoActivity extends Activity { private boolean myHideOpenButton; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); Thread.setDefaultUncaughtExceptionHandler( new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this) ); diff --git a/src/org/geometerplus/android/fbreader/CancelActivity.java b/src/org/geometerplus/android/fbreader/CancelActivity.java index 8205d6820..b207e23a0 100644 --- a/src/org/geometerplus/android/fbreader/CancelActivity.java +++ b/src/org/geometerplus/android/fbreader/CancelActivity.java @@ -33,8 +33,8 @@ public class CancelActivity extends ListActivity { static final String ITEM_SUMMARY = "summary"; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); final ActionListAdapter adapter = new ActionListAdapter(getIntent()); setListAdapter(adapter); diff --git a/src/org/geometerplus/android/fbreader/ControlButtonPanel.java b/src/org/geometerplus/android/fbreader/ControlButtonPanel.java index 898aa9bca..5516ded58 100644 --- a/src/org/geometerplus/android/fbreader/ControlButtonPanel.java +++ b/src/org/geometerplus/android/fbreader/ControlButtonPanel.java @@ -19,104 +19,78 @@ package org.geometerplus.android.fbreader; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import org.geometerplus.zlibrary.core.application.ZLApplication; -class ControlButtonPanel implements ZLApplication.ButtonPanel { +import org.geometerplus.zlibrary.text.view.ZLTextWordCursor; + +import org.geometerplus.fbreader.fbreader.FBReaderApp; + +abstract class ControlButtonPanel implements ZLApplication.ButtonPanel { + public final FBReaderApp Reader; + public ZLTextWordCursor StartPosition; + private boolean myVisible; + protected ControlPanel myControlPanel; - private static LinkedList ourPanels = new LinkedList(); - + ControlButtonPanel(FBReaderApp fbReader) { + Reader = fbReader; + fbReader.registerButtonPanel(this); + } public final void hide() { hide(false); } public void updateStates() { - if (myControlPanel != null) { - myControlPanel.updateStates(); - } - } - - public final void register() { - ZLApplication.Instance().registerButtonPanel(this); - ourPanels.add(this); } public final boolean hasControlPanel() { return myControlPanel != null; } - public final void setControlPanel(ControlPanel panel, RelativeLayout root, boolean fillWidth) { - myControlPanel = panel; - RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams( - fillWidth ? ViewGroup.LayoutParams.FILL_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT - ); - p.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); - p.addRule(RelativeLayout.CENTER_HORIZONTAL); - myControlPanel.setVisibility(View.GONE); - root.addView(myControlPanel, p); - } - private final void removeControlPanel() { if (myControlPanel != null) { - ViewGroup root = (ViewGroup) myControlPanel.getParent(); + ViewGroup root = (ViewGroup)myControlPanel.getParent(); myControlPanel.hide(false); root.removeView(myControlPanel); myControlPanel = null; } } - public static void removeControlPanels() { - for (ControlButtonPanel panel: ourPanels) { - panel.removeControlPanel(); + public static void removeControlPanels(ZLApplication application) { + for (ZLApplication.ButtonPanel panel : application.buttonPanels()) { + ((ControlButtonPanel)panel).removeControlPanel(); } } - public static void restoreVisibilities() { - for (ControlButtonPanel panel: ourPanels) { - panel.setVisibility(panel.myVisible); + public static void restoreVisibilities(ZLApplication application) { + for (ZLApplication.ButtonPanel panel : application.buttonPanels()) { + final ControlButtonPanel p = (ControlButtonPanel)panel; + p.setVisibility(p.myVisible); } } - public static void saveVisibilities() { - for (ControlButtonPanel panel: ourPanels) { - panel.myVisible = panel.getVisibility(); + public static void saveVisibilities(ZLApplication application) { + for (ZLApplication.ButtonPanel panel : application.buttonPanels()) { + final ControlButtonPanel p = (ControlButtonPanel)panel; + p.myVisible = p.getVisibility(); } } - public static void restoreVisibilitiesFrom(List buffer) { - Iterator it = buffer.iterator(); - for (ControlButtonPanel panel: ourPanels) { - panel.setVisibility(it.next()); - } - } - - public static void saveVisibilitiesTo(List buffer) { - buffer.clear(); - for (ControlButtonPanel panel: ourPanels) { - buffer.add(panel.getVisibility()); - } - } - - public static void hideAllPendingNotify() { - for (ControlButtonPanel panel: ourPanels) { - if (panel.myControlPanel != null && panel.getVisibility()) { - panel.myControlPanel.hide(false); + public static void hideAllPendingNotify(ZLApplication application) { + for (ZLApplication.ButtonPanel panel : application.buttonPanels()) { + final ControlButtonPanel p = (ControlButtonPanel)panel; + if (p.myControlPanel != null && p.getVisibility()) { + p.myControlPanel.hide(false); } } } - public final boolean getVisibility() { if (myControlPanel != null) { return myControlPanel.getVisibility() == View.VISIBLE; @@ -124,7 +98,7 @@ class ControlButtonPanel implements ZLApplication.ButtonPanel { return false; } - public final void setVisibility(boolean visible) { + private void setVisibility(boolean visible) { if (visible) { show(false); } else { @@ -133,30 +107,42 @@ class ControlButtonPanel implements ZLApplication.ButtonPanel { } private void hideOthers() { - for (ControlButtonPanel panel: ourPanels) { + for (ZLApplication.ButtonPanel panel : Reader.buttonPanels()) { if (panel != this) { - panel.hide(false); + ((ControlButtonPanel)panel).hide(false); } } } public final void show(boolean animate) { if (myControlPanel != null && !getVisibility()) { - myVisible = true; hideOthers(); onShow(); myControlPanel.show(animate); } } + public final void initPosition() { + if (StartPosition == null) { + StartPosition = new ZLTextWordCursor(Reader.getTextView().getStartCursor()); + } + } + + public final void storePosition() { + if (StartPosition != null && + !StartPosition.equals(Reader.getTextView().getStartCursor())) { + Reader.addInvisibleBookmark(StartPosition); + } + } + public final void hide(boolean animate) { - myVisible = false; if (myControlPanel != null && getVisibility()) { onHide(); myControlPanel.hide(animate); } } + public abstract void createControlPanel(FBReader activity, RelativeLayout root); // callback methods public void onShow() {} diff --git a/src/org/geometerplus/android/fbreader/ControlPanel.java b/src/org/geometerplus/android/fbreader/ControlPanel.java index a7f8f8a05..60fbdce63 100644 --- a/src/org/geometerplus/android/fbreader/ControlPanel.java +++ b/src/org/geometerplus/android/fbreader/ControlPanel.java @@ -19,14 +19,10 @@ package org.geometerplus.android.fbreader; -import java.util.ArrayList; - import android.os.Handler; import android.os.Message; import android.content.Context; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; +import android.view.*; import android.view.animation.AlphaAnimation; import android.widget.*; @@ -34,22 +30,8 @@ import org.geometerplus.zlibrary.ui.android.R; import org.geometerplus.zlibrary.core.application.ZLApplication; -class ActionButton extends ZoomButton { - final String ActionId; - final boolean IsCloseButton; - - ActionButton(Context context, String actionId, boolean isCloseButton) { - super(context); - ActionId = actionId; - IsCloseButton = isCloseButton; - } -} - -public class ControlPanel extends LinearLayout implements View.OnClickListener { - private final ArrayList myButtons = new ArrayList(); - private final LinearLayout myPlateLayout; - - public ControlPanel(Context context) { +public class ControlPanel extends LinearLayout { + public ControlPanel(Context context, RelativeLayout root, boolean fillWidth) { super(context); setFocusable(false); @@ -57,25 +39,18 @@ public class ControlPanel extends LinearLayout implements View.OnClickListener { final LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.control_panel, this, true); - myPlateLayout = (LinearLayout)findViewById(R.id.tools_plate); + + RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams( + fillWidth ? ViewGroup.LayoutParams.FILL_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT + ); + p.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + p.addRule(RelativeLayout.CENTER_HORIZONTAL); + root.addView(this, p); + + setVisibility(View.GONE); } - public void addButton(String actionId, boolean isCloseButton, int imageId) { - final ActionButton button = new ActionButton(getContext(), actionId, isCloseButton); - button.setImageResource(imageId); - button.setOnClickListener(this); - myPlateLayout.addView(button); - myButtons.add(button); - } - - public void onClick(View view) { - final ActionButton button = (ActionButton)view; - ZLApplication.Instance().doAction(button.ActionId); - if (button.IsCloseButton) { - hide(true); - } - } - @Override public boolean onTouchEvent(MotionEvent event) { return true; @@ -121,28 +96,8 @@ public class ControlPanel extends LinearLayout implements View.OnClickListener { startAnimation(animation); setVisibility(visibility); } - - public void updateStates() { - final ZLApplication application = ZLApplication.Instance(); - for (ActionButton button : myButtons) { - button.setEnabled(application.isActionEnabled(button.ActionId)); - } - } - - @Override - public boolean hasFocus() { - for (ActionButton button : myButtons) { - if (button.hasFocus()) { - return true; - } - } - return false; - } - public void setExtension(View view) { - if (view != null) { - myPlateLayout.removeAllViews(); - myPlateLayout.addView(view); - } + public void addView(View view) { + ((LinearLayout)findViewById(R.id.tools_plate)).addView(view); } } diff --git a/src/org/geometerplus/android/fbreader/FBReader.java b/src/org/geometerplus/android/fbreader/FBReader.java index 485540be3..ea7f75c22 100644 --- a/src/org/geometerplus/android/fbreader/FBReader.java +++ b/src/org/geometerplus/android/fbreader/FBReader.java @@ -19,24 +19,17 @@ package org.geometerplus.android.fbreader; -import java.util.LinkedList; - import android.app.SearchManager; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.view.*; -import android.widget.*; +import android.view.WindowManager; +import android.widget.RelativeLayout; -import org.geometerplus.zlibrary.core.application.ZLApplication; import org.geometerplus.zlibrary.core.filesystem.ZLFile; -import org.geometerplus.zlibrary.core.resources.ZLResource; -import org.geometerplus.zlibrary.core.view.ZLView; -import org.geometerplus.zlibrary.text.view.ZLTextWordCursor; -import org.geometerplus.zlibrary.text.view.ZLTextView; import org.geometerplus.zlibrary.text.hyphenation.ZLTextHyphenator; import org.geometerplus.zlibrary.ui.android.R; @@ -45,7 +38,6 @@ import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication; import org.geometerplus.fbreader.fbreader.ActionCode; import org.geometerplus.fbreader.fbreader.FBReaderApp; -import org.geometerplus.fbreader.fbreader.FBView; import org.geometerplus.fbreader.bookmodel.BookModel; import org.geometerplus.fbreader.library.Book; @@ -61,36 +53,8 @@ public final class FBReader extends ZLAndroidActivity { private int myFullScreenFlag; - private class NavigationButtonPanel extends ControlButtonPanel { - public volatile boolean NavigateDragging; - public ZLTextWordCursor StartPosition; - - @Override - public void onShow() { - if (myControlPanel != null) { - setupNavigation(myControlPanel); - } - } - - @Override - public void updateStates() { - super.updateStates(); - if (!NavigateDragging && myControlPanel != null) { - setupNavigation(myControlPanel); - } - } - } - - private static class TextSearchButtonPanel extends ControlButtonPanel { - @Override - public void onHide() { - final ZLTextView textView = (ZLTextView)ZLApplication.Instance().getCurrentView(); - textView.clearFindResults(); - } - } - - private static TextSearchButtonPanel myTextSearchPanel; - private static NavigationButtonPanel myNavigatePanel; + private static TextSearchButtonPanel ourTextSearchPanel; + private static NavigationButtonPanel ourNavigatePanel; @Override protected ZLFile fileFromIntent(Intent intent) { @@ -113,16 +77,15 @@ public final class FBReader extends ZLAndroidActivity { getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, myFullScreenFlag ); - if (myTextSearchPanel == null) { - myTextSearchPanel = new TextSearchButtonPanel(); - myTextSearchPanel.register(); + + final FBReaderApp fbReader = (FBReaderApp)FBReaderApp.Instance(); + if (ourTextSearchPanel == null) { + ourTextSearchPanel = new TextSearchButtonPanel(fbReader); } - if (myNavigatePanel == null) { - myNavigatePanel = new NavigationButtonPanel(); - myNavigatePanel.register(); + if (ourNavigatePanel == null) { + ourNavigatePanel = new NavigationButtonPanel(fbReader); } - final FBReaderApp fbReader = (FBReaderApp)ZLApplication.Instance(); fbReader.addAction(ActionCode.SHOW_LIBRARY, new ShowLibraryAction(this, fbReader)); fbReader.addAction(ActionCode.SHOW_PREFERENCES, new ShowPreferencesAction(this, fbReader)); fbReader.addAction(ActionCode.SHOW_BOOK_INFO, new ShowBookInfoAction(this, fbReader)); @@ -145,16 +108,18 @@ public final class FBReader extends ZLAndroidActivity { final String pattern = intent.getStringExtra(SearchManager.QUERY); final Handler successHandler = new Handler() { public void handleMessage(Message message) { - showTextSearchControls(true); + ourTextSearchPanel.show(true); } }; final Handler failureHandler = new Handler() { public void handleMessage(Message message) { UIUtil.showErrorMessage(FBReader.this, "textNotFound"); + ourTextSearchPanel.StartPosition = null; } }; final Runnable runnable = new Runnable() { public void run() { + ourTextSearchPanel.initPosition(); final FBReaderApp fbReader = (FBReaderApp)FBReaderApp.Instance(); fbReader.TextSearchPatternOption.setValue(pattern); if (fbReader.getTextView().search(pattern, true, false, false, false) != 0) { @@ -183,52 +148,38 @@ public final class FBReader extends ZLAndroidActivity { } final RelativeLayout root = (RelativeLayout)findViewById(R.id.root_view); - if (!myTextSearchPanel.hasControlPanel()) { - final ControlPanel panel = new ControlPanel(this); - - panel.addButton(ActionCode.FIND_PREVIOUS, false, R.drawable.text_search_previous); - panel.addButton(ActionCode.CLEAR_FIND_RESULTS, true, R.drawable.text_search_close); - panel.addButton(ActionCode.FIND_NEXT, false, R.drawable.text_search_next); - - myTextSearchPanel.setControlPanel(panel, root, false); + if (!ourTextSearchPanel.hasControlPanel()) { + ourTextSearchPanel.createControlPanel(this, root); } - if (!myNavigatePanel.hasControlPanel()) { - final ControlPanel panel = new ControlPanel(this); - final View layout = getLayoutInflater().inflate(R.layout.navigate, panel, false); - createNavigation(layout); - panel.setExtension(layout); - myNavigatePanel.setControlPanel(panel, root, true); + if (!ourNavigatePanel.hasControlPanel()) { + ourNavigatePanel.createControlPanel(this, root); } } @Override public void onResume() { super.onResume(); - sendBroadcast(new Intent(getApplicationContext(), KillerCallback.class)); - ControlButtonPanel.restoreVisibilities(); + try { + sendBroadcast(new Intent(getApplicationContext(), KillerCallback.class)); + } catch (Throwable t) { + } + ControlButtonPanel.restoreVisibilities(FBReaderApp.Instance()); } @Override public void onPause() { - ControlButtonPanel.saveVisibilities(); + ControlButtonPanel.saveVisibilities(FBReaderApp.Instance()); super.onPause(); } @Override public void onStop() { - ControlButtonPanel.removeControlPanels(); + ControlButtonPanel.removeControlPanels(FBReaderApp.Instance()); super.onStop(); } - void showTextSearchControls(boolean show) { - if (show) { - myTextSearchPanel.show(true); - } else { - myTextSearchPanel.hide(false); - } - } - - protected ZLApplication createApplication(ZLFile file) { + @Override + protected FBReaderApp createApplication(ZLFile file) { if (SQLiteBooksDatabase.Instance() == null) { new SQLiteBooksDatabase(this, "READER"); } @@ -237,24 +188,23 @@ public final class FBReader extends ZLAndroidActivity { @Override public boolean onSearchRequested() { - final LinkedList visibilities = new LinkedList(); - ControlButtonPanel.saveVisibilitiesTo(visibilities); - ControlButtonPanel.hideAllPendingNotify(); + final FBReaderApp fbreader = (FBReaderApp)FBReaderApp.Instance(); + ControlButtonPanel.saveVisibilities(fbreader); + ControlButtonPanel.hideAllPendingNotify(fbreader); final SearchManager manager = (SearchManager)getSystemService(SEARCH_SERVICE); manager.setOnCancelListener(new SearchManager.OnCancelListener() { public void onCancel() { - ControlButtonPanel.restoreVisibilitiesFrom(visibilities); + ControlButtonPanel.restoreVisibilities(fbreader); manager.setOnCancelListener(null); } }); - final FBReaderApp fbreader = (FBReaderApp)ZLApplication.Instance(); startSearch(fbreader.TextSearchPatternOption.getValue(), true, null, false); return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - final FBReaderApp fbreader = (FBReaderApp)ZLApplication.Instance(); + final FBReaderApp fbreader = (FBReaderApp)FBReaderApp.Instance(); switch (requestCode) { case REPAINT_CODE: { @@ -276,88 +226,7 @@ public final class FBReader extends ZLAndroidActivity { } } - public boolean navigate() { - if (myNavigatePanel.getVisibility()) { - return false; - } - final ZLTextView textView = (ZLTextView)ZLApplication.Instance().getCurrentView(); - myNavigatePanel.NavigateDragging = false; - myNavigatePanel.StartPosition = new ZLTextWordCursor(textView.getStartCursor()); - myNavigatePanel.show(true); - return true; - } - - private final void createNavigation(View layout) { - final FBReaderApp fbreader = (FBReaderApp)ZLApplication.Instance(); - final SeekBar slider = (SeekBar)layout.findViewById(R.id.book_position_slider); - final TextView text = (TextView)layout.findViewById(R.id.book_position_text); - - slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - private void gotoPage(int page) { - final ZLTextView view = fbreader.getTextView(); - if (page == 1) { - view.gotoHome(); - } else { - view.gotoPage(page); - } - fbreader.repaintView(); - } - - public void onStopTrackingTouch(SeekBar seekBar) { - myNavigatePanel.NavigateDragging = false; - } - - public void onStartTrackingTouch(SeekBar seekBar) { - myNavigatePanel.NavigateDragging = true; - } - - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - final int page = progress + 1; - final int pagesNumber = seekBar.getMax() + 1; - text.setText(makeProgressText(page, pagesNumber)); - gotoPage(page); - } - } - }); - - final Button btnOk = (Button)layout.findViewById(android.R.id.button1); - final Button btnCancel = (Button)layout.findViewById(android.R.id.button3); - View.OnClickListener listener = new View.OnClickListener() { - public void onClick(View v) { - final ZLTextWordCursor position = myNavigatePanel.StartPosition; - myNavigatePanel.StartPosition = null; - if (v == btnCancel && position != null) { - fbreader.getTextView().gotoPosition(position); - } else if (v == btnOk) { - fbreader.addInvisibleBookmark(position); - } - myNavigatePanel.hide(true); - } - }; - btnOk.setOnClickListener(listener); - btnCancel.setOnClickListener(listener); - final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button"); - btnOk.setText(buttonResource.getResource("ok").getValue()); - btnCancel.setText(buttonResource.getResource("cancel").getValue()); - } - - private final void setupNavigation(ControlPanel panel) { - final SeekBar slider = (SeekBar)panel.findViewById(R.id.book_position_slider); - final TextView text = (TextView)panel.findViewById(R.id.book_position_text); - - final ZLTextView textView = (ZLTextView)ZLApplication.Instance().getCurrentView(); - final int page = textView.computeCurrentPage(); - final int pagesNumber = textView.computePageNumber(); - - if (slider.getMax() != pagesNumber - 1 || slider.getProgress() != page - 1) { - slider.setMax(pagesNumber - 1); - slider.setProgress(page - 1); - text.setText(makeProgressText(page, pagesNumber)); - } - } - - private static String makeProgressText(int page, int pagesNumber) { - return "" + page + " / " + pagesNumber; + public void navigate() { + ourNavigatePanel.runNavigation(); } } diff --git a/src/org/geometerplus/android/fbreader/NavigationButtonPanel.java b/src/org/geometerplus/android/fbreader/NavigationButtonPanel.java new file mode 100644 index 000000000..d7cc19bfe --- /dev/null +++ b/src/org/geometerplus/android/fbreader/NavigationButtonPanel.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009-2011 Geometer Plus + * + * 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 android.view.View; +import android.widget.Button; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import org.geometerplus.zlibrary.core.resources.ZLResource; + +import org.geometerplus.zlibrary.text.view.ZLTextView; +import org.geometerplus.zlibrary.text.view.ZLTextWordCursor; + +import org.geometerplus.zlibrary.ui.android.R; + +import org.geometerplus.fbreader.fbreader.FBReaderApp; + +final class NavigationButtonPanel extends ControlButtonPanel { + private volatile boolean myIsInProgress; + + NavigationButtonPanel(FBReaderApp fbReader) { + super(fbReader); + } + + public void runNavigation() { + if (!getVisibility()) { + myIsInProgress = false; + initPosition(); + show(true); + } + } + + @Override + public void onShow() { + if (myControlPanel != null) { + setupNavigation(myControlPanel); + } + } + + @Override + public void updateStates() { + super.updateStates(); + if (!myIsInProgress && myControlPanel != null) { + setupNavigation(myControlPanel); + } + } + + @Override + public void createControlPanel(FBReader activity, RelativeLayout root) { + myControlPanel = new ControlPanel(activity, root, true); + + final View layout = activity.getLayoutInflater().inflate(R.layout.navigate, myControlPanel, false); + + final SeekBar slider = (SeekBar)layout.findViewById(R.id.book_position_slider); + final TextView text = (TextView)layout.findViewById(R.id.book_position_text); + + slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + private void gotoPage(int page) { + final ZLTextView view = Reader.getTextView(); + if (page == 1) { + view.gotoHome(); + } else { + view.gotoPage(page); + } + Reader.repaintView(); + } + + public void onStopTrackingTouch(SeekBar seekBar) { + myIsInProgress = false; + } + + public void onStartTrackingTouch(SeekBar seekBar) { + myIsInProgress = true; + } + + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + final int page = progress + 1; + final int pagesNumber = seekBar.getMax() + 1; + text.setText(makeProgressText(page, pagesNumber)); + gotoPage(page); + } + } + }); + + final Button btnOk = (Button)layout.findViewById(android.R.id.button1); + final Button btnCancel = (Button)layout.findViewById(android.R.id.button3); + View.OnClickListener listener = new View.OnClickListener() { + public void onClick(View v) { + final ZLTextWordCursor position = StartPosition; + if (v == btnCancel && position != null) { + Reader.getTextView().gotoPosition(position); + } else if (v == btnOk) { + storePosition(); + } + StartPosition = null; + hide(true); + } + }; + btnOk.setOnClickListener(listener); + btnCancel.setOnClickListener(listener); + final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button"); + btnOk.setText(buttonResource.getResource("ok").getValue()); + btnCancel.setText(buttonResource.getResource("cancel").getValue()); + + myControlPanel.addView(layout); + } + + private void setupNavigation(ControlPanel panel) { + final SeekBar slider = (SeekBar)panel.findViewById(R.id.book_position_slider); + final TextView text = (TextView)panel.findViewById(R.id.book_position_text); + + final ZLTextView textView = Reader.getTextView(); + final int page = textView.computeCurrentPage(); + final int pagesNumber = textView.computePageNumber(); + + if (slider.getMax() != pagesNumber - 1 || slider.getProgress() != page - 1) { + slider.setMax(pagesNumber - 1); + slider.setProgress(page - 1); + text.setText(makeProgressText(page, pagesNumber)); + } + } + + private static String makeProgressText(int page, int pagesNumber) { + return page + " / " + pagesNumber; + } +} diff --git a/src/org/geometerplus/android/fbreader/TextSearchButtonPanel.java b/src/org/geometerplus/android/fbreader/TextSearchButtonPanel.java new file mode 100644 index 000000000..7c6ea4733 --- /dev/null +++ b/src/org/geometerplus/android/fbreader/TextSearchButtonPanel.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009-2011 Geometer Plus + * + * 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.ArrayList; + +import android.content.Context; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.ZoomButton; + +import org.geometerplus.zlibrary.ui.android.R; + +import org.geometerplus.fbreader.fbreader.ActionCode; +import org.geometerplus.fbreader.fbreader.FBReaderApp; + +class ActionButton extends ZoomButton { + final String ActionId; + final boolean IsCloseButton; + + ActionButton(Context context, String actionId, boolean isCloseButton) { + super(context); + ActionId = actionId; + IsCloseButton = isCloseButton; + } +} + +final class TextSearchButtonPanel extends ControlButtonPanel implements View.OnClickListener { + private final ArrayList myButtons = new ArrayList(); + + TextSearchButtonPanel(FBReaderApp fbReader) { + super(fbReader); + } + + @Override + public void onHide() { + Reader.getTextView().clearFindResults(); + } + + @Override + public void createControlPanel(FBReader activity, RelativeLayout root) { + myControlPanel = new ControlPanel(activity, root, false); + + addButton(ActionCode.FIND_PREVIOUS, false, R.drawable.text_search_previous); + addButton(ActionCode.CLEAR_FIND_RESULTS, true, R.drawable.text_search_close); + addButton(ActionCode.FIND_NEXT, false, R.drawable.text_search_next); + } + + private void addButton(String actionId, boolean isCloseButton, int imageId) { + final ActionButton button = new ActionButton(myControlPanel.getContext(), actionId, isCloseButton); + button.setImageResource(imageId); + myControlPanel.addView(button); + button.setOnClickListener(this); + myButtons.add(button); + } + + @Override + public void updateStates() { + for (ActionButton button : myButtons) { + button.setEnabled(Reader.isActionEnabled(button.ActionId)); + } + } + + public void onClick(View view) { + final ActionButton button = (ActionButton)view; + Reader.doAction(button.ActionId); + if (button.IsCloseButton && myControlPanel != null) { + storePosition(); + StartPosition = null; + myControlPanel.hide(true); + } + } +} diff --git a/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java b/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java index 171049c5e..0f91fc5e5 100644 --- a/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java +++ b/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java @@ -35,8 +35,8 @@ public class ImageViewActivity extends Activity { Bitmap myBitmap; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); final ZLAndroidApplication application = ZLAndroidApplication.Instance(); diff --git a/src/org/geometerplus/android/fbreader/library/FileManager.java b/src/org/geometerplus/android/fbreader/library/FileManager.java index deb74da5e..dabd48935 100644 --- a/src/org/geometerplus/android/fbreader/library/FileManager.java +++ b/src/org/geometerplus/android/fbreader/library/FileManager.java @@ -47,8 +47,8 @@ public final class FileManager extends BaseActivity { private String myPath; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onCreate(Bundle icicle) { + super.onCreate(icicle); if (DatabaseInstance == null || LibraryInstance == null) { finish(); diff --git a/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java index fec81267a..ec29e172e 100644 --- a/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java +++ b/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java @@ -52,8 +52,8 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve private BookDownloaderServiceConnection myConnection; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); if (!NetworkView.Instance().isInitialized()) { finish(); diff --git a/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java b/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java index 3ea9c7f34..56d40117c 100644 --- a/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java +++ b/src/org/geometerplus/fbreader/fbreader/FBReaderApp.java @@ -239,6 +239,7 @@ public final class FBReaderApp extends ZLApplication { } public void gotoBookmark(Bookmark bookmark) { + addInvisibleBookmark(); final String modelId = bookmark.ModelId; if (modelId == null) { BookTextView.gotoPosition(bookmark); @@ -354,7 +355,6 @@ public final class FBReaderApp extends ZLApplication { { final Bookmark b = ((BookmarkDescription)description).Bookmark; b.delete(); - addInvisibleBookmark(); gotoBookmark(b); break; } @@ -366,6 +366,11 @@ public final class FBReaderApp extends ZLApplication { private void updateInvisibleBookmarksList(Bookmark b) { if (Model.Book != null && b != null) { + for (Bookmark bm : Bookmark.invisibleBookmarks(Model.Book)) { + if (b.equals(bm)) { + bm.delete(); + } + } b.save(); final List bookmarks = Bookmark.invisibleBookmarks(Model.Book); for (int i = 3; i < bookmarks.size(); ++i) { diff --git a/src/org/geometerplus/fbreader/formats/html/HtmlReader.java b/src/org/geometerplus/fbreader/formats/html/HtmlReader.java index e7087b1cc..6a2a9bf87 100644 --- a/src/org/geometerplus/fbreader/formats/html/HtmlReader.java +++ b/src/org/geometerplus/fbreader/formats/html/HtmlReader.java @@ -259,6 +259,9 @@ public class HtmlReader extends BookReader implements ZLHtmlReader { if (ref.charAt(0) == '#') { myHyperlinkType = FBTextKind.FOOTNOTE; ref = ref.substring(1); + } else if (ref.charAt(0) == '&') { + myHyperlinkType = FBTextKind.INTERNAL_HYPERLINK; + ref = ref.substring(1); } else { myHyperlinkType = FBTextKind.EXTERNAL_HYPERLINK; } diff --git a/src/org/geometerplus/fbreader/formats/pdb/MobipocketHtmlBookReader.java b/src/org/geometerplus/fbreader/formats/pdb/MobipocketHtmlBookReader.java index f537fa247..28b24e785 100644 --- a/src/org/geometerplus/fbreader/formats/pdb/MobipocketHtmlBookReader.java +++ b/src/org/geometerplus/fbreader/formats/pdb/MobipocketHtmlBookReader.java @@ -122,7 +122,7 @@ public class MobipocketHtmlBookReader extends HtmlReader { } } myFileposReferences.add(filePosition); - // TODO: add hyperlink control + attributes.put(new ZLByteBuffer("href"), new ZLByteBuffer("&filepos" + filePosition)); } catch (NumberFormatException e) { } } @@ -182,12 +182,21 @@ public class MobipocketHtmlBookReader extends HtmlReader { if (length <= 0) { break; } - addImage("" + index, new ZLFileImage(MimeTypes.MIME_IMAGE_AUTO, Model.Book.File, offset, length)); + addImage("" + (index + 1), new ZLFileImage(MimeTypes.MIME_IMAGE_AUTO, Model.Book.File, offset, length)); } } @Override public void endDocumentHandler() { + for (Integer entry: myFileposReferences) { + final SortedMap subMap = + myPositionToParagraph.tailMap(entry); + if (subMap.isEmpty()) { + break; + } + addHyperlinkLabel("filepos" + entry, subMap.get(subMap.firstKey())); + } + for (Map.Entry entry : myTocEntries.entrySet()) { final SortedMap subMap = myPositionToParagraph.tailMap(entry.getKey()); diff --git a/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java b/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java index c9cfb7f16..032089f23 100644 --- a/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java +++ b/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java @@ -22,7 +22,9 @@ package org.geometerplus.fbreader.formats.pdb; import java.io.*; import org.geometerplus.zlibrary.core.filesystem.ZLFile; +import org.geometerplus.zlibrary.core.image.ZLFileImage; import org.geometerplus.zlibrary.core.image.ZLImage; +import org.geometerplus.zlibrary.core.constants.MimeTypes; import org.geometerplus.zlibrary.core.encoding.ZLEncodingCollection; import org.geometerplus.zlibrary.core.language.ZLLanguageUtil; @@ -202,20 +204,14 @@ public class MobipocketPlugin extends PdbPlugin { coverIndex = thumbIndex; } - // TODO: implement - /*final MobipocketStream mpStream = new MobipocketStream(file); - - int index = pbStream.firstImageLocationIndex(file.path()); - if (index >= 0) { - std::pair imageLocation = pbStream.imageLocation(pbStream.header(), index + coverIndex); - if ((imageLocation.first > 0) && (imageLocation.second > 0)) { - return new ZLFileImage( - file, - imageLocation.first, - imageLocation.second - ); + MobipocketStream myMobipocketStream = new MobipocketStream(file); + int start = myMobipocketStream.getImageOffset(coverIndex); + if (start >= 0) { + int len = myMobipocketStream.getImageLength(coverIndex); + if (len > 0) { + return new ZLFileImage(MimeTypes.MIME_IMAGE_AUTO, file, start, len); } - }*/ + } return null; } catch (IOException e) { return null; diff --git a/src/org/geometerplus/fbreader/formats/pdb/MobipocketStream.java b/src/org/geometerplus/fbreader/formats/pdb/MobipocketStream.java index 1c33344eb..ba9435db2 100644 --- a/src/org/geometerplus/fbreader/formats/pdb/MobipocketStream.java +++ b/src/org/geometerplus/fbreader/formats/pdb/MobipocketStream.java @@ -25,6 +25,7 @@ import org.geometerplus.zlibrary.core.filesystem.ZLFile; class MobipocketStream extends PalmDocLikeStream { private final int myFileSize; + private final int myImageStartIndex; MobipocketStream(ZLFile file) throws IOException { super(file); @@ -39,11 +40,14 @@ class MobipocketStream extends PalmDocLikeStream { } myBuffer = new byte[maxRecordSize]; myRecordIndex = 0; + + PdbUtil.skip(myBase, 96); + myImageStartIndex = (int)PdbUtil.readInt(myBase); } int getImageOffset(int index) { try { - return myHeader.Offsets[index + myMaxRecordIndex + 1]; + return myHeader.Offsets[index + myImageStartIndex]; } catch (ArrayIndexOutOfBoundsException e) { return -1; } @@ -51,7 +55,7 @@ class MobipocketStream extends PalmDocLikeStream { int getImageLength(int index) { try { - final int i = index + myMaxRecordIndex + 1; + final int i = index + myImageStartIndex; final int start = myHeader.Offsets[i]; final int end = (i == myHeader.Offsets.length) ? myFileSize : myHeader.Offsets[i + 1]; return end - start; diff --git a/src/org/geometerplus/zlibrary/core/application/ZLApplication.java b/src/org/geometerplus/zlibrary/core/application/ZLApplication.java index cdd991ee4..4d769fb2f 100644 --- a/src/org/geometerplus/zlibrary/core/application/ZLApplication.java +++ b/src/org/geometerplus/zlibrary/core/application/ZLApplication.java @@ -199,7 +199,10 @@ public abstract class ZLApplication { void updateStates(); void hide(); } - private final HashSet myPanels = new HashSet(); + private final List myPanels = new LinkedList(); + public final List buttonPanels() { + return Collections.unmodifiableList(myPanels); + } public final void registerButtonPanel(ButtonPanel panel) { myPanels.add(panel); } diff --git a/src/org/geometerplus/zlibrary/core/html/ZLByteBuffer.java b/src/org/geometerplus/zlibrary/core/html/ZLByteBuffer.java index dadfc1235..08050e97f 100644 --- a/src/org/geometerplus/zlibrary/core/html/ZLByteBuffer.java +++ b/src/org/geometerplus/zlibrary/core/html/ZLByteBuffer.java @@ -37,6 +37,11 @@ public final class ZLByteBuffer { this(20); } + public ZLByteBuffer(String value) { + myLength = value.length(); + myData = value.getBytes(); + } + ZLByteBuffer(ZLByteBuffer container) { final int len = container.myLength; myData = ZLArrayUtils.createCopy(container.myData, len, len); diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java b/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java index d357965b6..424854258 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java @@ -44,4 +44,24 @@ public abstract class ZLTextPosition implements Comparable { return getCharIndex() - position.getCharIndex(); } + + @Override + public int hashCode() { + return (getParagraphIndex() << 16) + (getElementIndex() << 8) + getCharIndex(); + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (!(object instanceof ZLTextPosition)) { + return false; + } + final ZLTextPosition position = (ZLTextPosition)object; + return + getParagraphIndex() == position.getParagraphIndex() && + getElementIndex() == position.getElementIndex() && + getCharIndex() == position.getCharIndex(); + } } diff --git a/src/org/geometerplus/zlibrary/ui/android/library/BugReportActivity.java b/src/org/geometerplus/zlibrary/ui/android/library/BugReportActivity.java index cb036dfdf..5b318bcb9 100644 --- a/src/org/geometerplus/zlibrary/ui/android/library/BugReportActivity.java +++ b/src/org/geometerplus/zlibrary/ui/android/library/BugReportActivity.java @@ -39,8 +39,8 @@ public class BugReportActivity extends Activity { } } - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onCreate(Bundle icicle) { + super.onCreate(icicle); setContentView(R.layout.bug_report_view); final String stackTrace = getIntent().getStringExtra(STACKTRACE); final TextView reportTextView = (TextView)findViewById(R.id.report_text);