diff --git a/data/resources/application/en.xml b/data/resources/application/en.xml
index 13762f08f..44193ed7f 100644
--- a/data/resources/application/en.xml
+++ b/data/resources/application/en.xml
@@ -20,6 +20,9 @@
+
+
+
@@ -250,8 +253,9 @@
-
-
+
+
+
diff --git a/data/resources/application/ru.xml b/data/resources/application/ru.xml
index a9d3bafa0..379fb4b16 100644
--- a/data/resources/application/ru.xml
+++ b/data/resources/application/ru.xml
@@ -253,6 +253,7 @@
+
diff --git a/platform/android/res/layout/bookmarks.xml b/platform/android/res/layout/bookmarks.xml
new file mode 100644
index 000000000..484e75692
--- /dev/null
+++ b/platform/android/res/layout/bookmarks.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/platform/android/src/org/geometerplus/android/fbreader/BookmarksActivity.java b/platform/android/src/org/geometerplus/android/fbreader/BookmarksActivity.java
index 860326e46..e3f8bb1b5 100644
--- a/platform/android/src/org/geometerplus/android/fbreader/BookmarksActivity.java
+++ b/platform/android/src/org/geometerplus/android/fbreader/BookmarksActivity.java
@@ -19,69 +19,119 @@
package org.geometerplus.android.fbreader;
+import java.util.*;
+
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import android.content.Context;
-import android.app.ListActivity;
+import android.app.TabActivity;
import android.graphics.drawable.Drawable;
import org.geometerplus.zlibrary.core.resources.ZLResource;
+import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.text.view.impl.*;
import org.geometerplus.zlibrary.ui.android.R;
+import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.fbreader.fbreader.FBReader;
import org.geometerplus.fbreader.library.*;
-public class BookmarksActivity extends ListActivity {
+public class BookmarksActivity extends TabActivity {
private static final int OPEN_ITEM_ID = 0;
private static final int EDIT_ITEM_ID = 1;
private static final int DELETE_ITEM_ID = 2;
- private BookmarkList myBookmarks;
+ private List myAllBooksBookmarks;
+ private final List myThisBookBookmarks = new LinkedList();
+ private final List mySearchResults = new LinkedList();
+
+ private ListView myThisBookView;
+ private ListView myAllBooksView;
+ private ListView mySearchResultsView;
+
+ private final ZLResource myResource = ZLResource.resource("bookmarksView");
+
+ private ListView createTab(String tag, int id) {
+ final TabHost host = getTabHost();
+ final String label = myResource.getResource(tag).getValue();
+ host.addTab(host.newTabSpec(tag).setIndicator(label).setContent(id));
+ return (ListView)findViewById(id);
+ }
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
+
requestWindowFeature(Window.FEATURE_NO_TITLE);
- myBookmarks = new BookmarkList(((FBReader)FBReader.Instance()).Model.Book);
- final BookmarksAdapter adapter = new BookmarksAdapter();
- final ListView listView = getListView();
- listView.setAdapter(adapter);
- listView.setOnItemClickListener(adapter);
- listView.setOnCreateContextMenuListener(adapter);
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+
+ final TabHost host = getTabHost();
+ LayoutInflater.from(this).inflate(R.layout.bookmarks, host.getTabContentView(), true);
+
+ myAllBooksBookmarks = Bookmark.bookmarks();
+ Collections.sort(myAllBooksBookmarks, new Bookmark.ByTimeComparator());
+ final long bookId = ((FBReader)FBReader.Instance()).Model.Book.getId();
+ for (Bookmark bookmark : myAllBooksBookmarks) {
+ if (bookmark.getBookId() == bookId) {
+ myThisBookBookmarks.add(bookmark);
+ }
+ }
+
+ myThisBookView = createTab("thisBook", R.id.this_book);
+ new BookmarksAdapter(myThisBookView, myThisBookBookmarks, true);
+
+ myAllBooksView = createTab("allBooks", R.id.all_books);
+ new BookmarksAdapter(myAllBooksView, myAllBooksBookmarks, false);
+
+ findViewById(R.id.search_results).setVisibility(View.GONE);
}
@Override
public void onPause() {
- myBookmarks.save();
+ for (Bookmark bookmark : myAllBooksBookmarks) {
+ bookmark.save();
+ }
super.onPause();
}
+ private void invalidateAllViews() {
+ myThisBookView.invalidateViews();
+ myThisBookView.requestLayout();
+ myAllBooksView.invalidateViews();
+ myAllBooksView.requestLayout();
+ }
+
@Override
public boolean onContextItemSelected(MenuItem item) {
final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position;
+ final ListView view = (ListView)getTabHost().getCurrentView();
+ final Bookmark bookmark = ((BookmarksAdapter)view.getAdapter()).getItem(position);
switch (item.getItemId()) {
case OPEN_ITEM_ID:
- gotoBookmark(position - 1);
+ gotoBookmark(bookmark);
return true;
case EDIT_ITEM_ID:
// TODO: implement
return true;
case DELETE_ITEM_ID:
- myBookmarks.removeBookmark(position - 1);
- getListView().invalidateViews();
- getListView().requestLayout();
+ bookmark.delete();
+ myThisBookBookmarks.remove(bookmark);
+ myAllBooksBookmarks.remove(bookmark);
+ invalidateAllViews();
return true;
}
return super.onContextItemSelected(item);
}
private void addBookmark() {
- ZLTextWordCursor cursor = ((FBReader)FBReader.Instance()).BookTextView.getStartCursor();
- if (!cursor.isNull()) {
+ final FBReader fbreader = (FBReader)FBReader.Instance();
+ ZLTextWordCursor cursor = fbreader.BookTextView.getStartCursor();
+
+ if (cursor.isNull()) {
// TODO: implement
+ return;
}
final ZLTextPosition position = new ZLTextPosition(cursor);
@@ -107,18 +157,44 @@ mainLoop:
} while ((builder.length() == 0) && cursor.nextParagraph());
// TODO: text edit dialog
- myBookmarks.addNewBookmark(builder.toString(), position);
- getListView().invalidateViews();
- getListView().requestLayout();
+ final Bookmark bookmark = new Bookmark(fbreader.Model.Book, builder.toString(), position);
+ myThisBookBookmarks.add(0, bookmark);
+ myAllBooksBookmarks.add(0, bookmark);
+ invalidateAllViews();
}
- private void gotoBookmark(int index) {
- myBookmarks.gotoBookmark(index, ((FBReader)FBReader.Instance()).BookTextView);
- finish();
+ private void gotoBookmark(Bookmark bookmark) {
+ bookmark.onOpen();
+ final FBReader fbreader = (FBReader)FBReader.Instance();
+ final long bookId = bookmark.getBookId();
+ if (fbreader.Model.Book.getId() != bookId) {
+ final Book book = Book.getById(bookId);
+ if (book != null) {
+ finish();
+ fbreader.openBook(book, bookmark.getPosition());
+ } else {
+ Toast.makeText(
+ this,
+ ZLResource.resource("errorMessage").getResource("cannotOpenBook").getValue(),
+ Toast.LENGTH_SHORT
+ ).show();
+ }
+ } else {
+ finish();
+ fbreader.BookTextView.gotoPosition(bookmark.getPosition());
+ }
}
private final class BookmarksAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener {
- BookmarksAdapter() {
+ private final List myBookmarks;
+ private final boolean myShowAddBookmarkButton;
+
+ BookmarksAdapter(ListView listView, List bookmarks, boolean showAddBookmarkButton) {
+ myBookmarks = bookmarks;
+ myShowAddBookmarkButton = showAddBookmarkButton;
+ listView.setAdapter(this);
+ listView.setOnItemClickListener(this);
+ listView.setOnCreateContextMenuListener(this);
}
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
@@ -135,12 +211,13 @@ mainLoop:
public View getView(int position, View convertView, ViewGroup parent) {
final View view = (convertView != null) ? convertView :
LayoutInflater.from(parent.getContext()).inflate(R.layout.bookmark_item, parent, false);
+ final Bookmark bookmark = getItem(position);
((ImageView)view.findViewById(R.id.bookmark_item_icon)).setImageResource(
- (position > 0) ? R.drawable.tree_icon_strut : R.drawable.tree_icon_plus
+ (bookmark != null) ? R.drawable.tree_icon_strut : R.drawable.tree_icon_plus
);
((TextView)view.findViewById(R.id.bookmark_item_text)).setText(
- (position > 0) ?
- getItem(position).getText() :
+ (bookmark != null) ?
+ bookmark.getText() :
ZLResource.resource("bookmarksView").getResource("new").getValue()
);
return view;
@@ -159,18 +236,22 @@ mainLoop:
}
public final Bookmark getItem(int position) {
- return (position > 0) ? myBookmarks.get(position - 1) : null;
+ if (myShowAddBookmarkButton) {
+ --position;
+ }
+ return (position >= 0) ? myBookmarks.get(position) : null;
}
public final int getCount() {
- return myBookmarks.size() + 1;
+ return myShowAddBookmarkButton ? myBookmarks.size() + 1 : myBookmarks.size();
}
public final void onItemClick(AdapterView parent, View view, int position, long id) {
- if (position == 0) {
- addBookmark();
+ final Bookmark bookmark = getItem(position);
+ if (bookmark != null) {
+ gotoBookmark(bookmark);
} else {
- gotoBookmark(position - 1);
+ addBookmark();
}
}
}
diff --git a/platform/android/src/org/geometerplus/android/fbreader/LibraryTabActivity.java b/platform/android/src/org/geometerplus/android/fbreader/LibraryTabActivity.java
index 8b353120e..3b9e675d6 100644
--- a/platform/android/src/org/geometerplus/android/fbreader/LibraryTabActivity.java
+++ b/platform/android/src/org/geometerplus/android/fbreader/LibraryTabActivity.java
@@ -37,8 +37,8 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
static LibraryTabActivity Instance;
final ZLStringOption mySelectedTabOption = new ZLStringOption("TabActivity", "SelectedTab", "");
- private ZLResource myResource = ZLResource.resource("libraryView");
-
+ private final ZLResource myResource = ZLResource.resource("libraryView");
+
private ListView createTab(String tag, int id) {
final TabHost host = getTabHost();
final String label = myResource.getResource(tag).getValue();
@@ -147,7 +147,7 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
}
finish();
final FBReader fbreader = (FBReader)FBReader.Instance();
- fbreader.openBook(((BookTree)tree).Book);
+ fbreader.openBook(((BookTree)tree).Book, null);
return true;
}
}
diff --git a/platform/android/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java b/platform/android/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
index fa9a8e900..9702b4906 100644
--- a/platform/android/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
+++ b/platform/android/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
@@ -30,7 +30,7 @@ import android.database.Cursor;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.dialogs.ZLDialogManager;
import org.geometerplus.zlibrary.core.options.ZLStringOption;
-import org.geometerplus.zlibrary.text.view.impl.ZLTextPosition;
+import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication;
import org.geometerplus.fbreader.library.*;
@@ -110,25 +110,28 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return new Date(cursor.getLong(index));
}
- private static final String BOOKS_TABLE = "Books";
- private static final String[] BOOKS_COLUMNS = { "book_id", "encoding", "language", "title" };
- private static final String FILE_NAME_CONDITION = "file_name = ?";
- protected long loadBook(Book book) {
- final Cursor cursor = myDatabase.query(
- BOOKS_TABLE,
- BOOKS_COLUMNS,
- FILE_NAME_CONDITION, new String[] { book.File.getPath() },
- null, null, null, null
- );
- long id = -1;
+ protected Book loadBook(long bookId) {
+ Book book = null;
+ final Cursor cursor = myDatabase.rawQuery("SELECT file_name,title,encoding,language FROM Books WHERE book_id = " + bookId, null);
if (cursor.moveToNext()) {
- id = cursor.getLong(0);
- book.setEncoding(cursor.getString(1));
- book.setLanguage(cursor.getString(2));
- book.setTitle(cursor.getString(3));
+ book = createBook(
+ bookId, cursor.getString(0), cursor.getString(1), cursor.getString(2), cursor.getString(3)
+ );
}
cursor.close();
- return id;
+ return book;
+ }
+
+ protected Book loadBook(String fileName) {
+ Book book = null;
+ final Cursor cursor = myDatabase.rawQuery("SELECT book_id,title,encoding,language FROM Books WHERE file_name = ?", new String[] { fileName });
+ if (cursor.moveToNext()) {
+ book = createBook(
+ cursor.getLong(0), fileName, cursor.getString(1), cursor.getString(2), cursor.getString(3)
+ );
+ }
+ cursor.close();
+ return book;
}
private boolean myTagCacheIsInitialized;
@@ -625,39 +628,102 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return ids;
}
- private SQLiteStatement myDeleteBookmarksStatement;
+ protected List listBookmarks(long bookId) {
+ LinkedList list = new LinkedList();
+ Cursor cursor = myDatabase.rawQuery(
+ "SELECT bookmark_id,book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char FROM Bookmarks WHERE book_id = ?", new String[] { "" + bookId }
+ );
+ while (cursor.moveToNext()) {
+ list.add(createBookmark(
+ cursor.getLong(0),
+ cursor.getLong(1),
+ cursor.getString(2),
+ getDate(cursor, 3),
+ getDate(cursor, 4),
+ getDate(cursor, 5),
+ (int)cursor.getLong(6),
+ (int)cursor.getLong(7),
+ (int)cursor.getLong(8),
+ (int)cursor.getLong(9)
+ ));
+ }
+ cursor.close();
+ return list;
+ }
+
+ protected List listAllBookmarks() {
+ LinkedList list = new LinkedList();
+ Cursor cursor = myDatabase.rawQuery(
+ "SELECT bookmark_id,book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char FROM Bookmarks", null
+ );
+ while (cursor.moveToNext()) {
+ list.add(createBookmark(
+ cursor.getLong(0),
+ cursor.getLong(1),
+ cursor.getString(2),
+ getDate(cursor, 3),
+ getDate(cursor, 4),
+ getDate(cursor, 5),
+ (int)cursor.getLong(6),
+ (int)cursor.getLong(7),
+ (int)cursor.getLong(8),
+ (int)cursor.getLong(9)
+ ));
+ }
+ cursor.close();
+ return list;
+ }
+
private SQLiteStatement myInsertBookmarkStatement;
- protected void saveBookmarks(final long bookId, final List list) {
- if (myDeleteBookmarksStatement == null) {
- myDeleteBookmarksStatement = myDatabase.compileStatement(
- "DELETE FROM Bookmarks WHERE book_id = ?"
- );
- myInsertBookmarkStatement = myDatabase.compileStatement(
- "INSERT INTO Bookmarks (book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char) VALUES (?,?,?,?,?,?,?,?,?)"
+ private SQLiteStatement myUpdateBookmarkStatement;
+ protected long saveBookmark(Bookmark bookmark) {
+ SQLiteStatement statement;
+ if (bookmark.getId() == -1) {
+ if (myInsertBookmarkStatement == null) {
+ myInsertBookmarkStatement = myDatabase.compileStatement(
+ "INSERT INTO Bookmarks (book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char) VALUES (?,?,?,?,?,?,?,?,?)"
+ );
+ }
+ statement = myInsertBookmarkStatement;
+ } else {
+ if (myUpdateBookmarkStatement == null) {
+ myUpdateBookmarkStatement = myDatabase.compileStatement(
+ "UPDATE Bookmarks SET book_id = ?, bookmark_text = ?, creation_time =?, modification_time = ?,access_time = ?, access_counter = ?, paragraph = ?, word = ?, char = ? WHERE bookmark_id = ?"
+ );
+ }
+ statement = myUpdateBookmarkStatement;
+ }
+
+ statement.bindLong(1, bookmark.getBookId());
+ statement.bindString(2, bookmark.getText());
+ bindDate(statement, 3, bookmark.getTime(Bookmark.CREATION));
+ bindDate(statement, 4, bookmark.getTime(Bookmark.MODIFICATION));
+ bindDate(statement, 5, bookmark.getTime(Bookmark.ACCESS));
+ statement.bindLong(6, bookmark.getAccessCount());
+ final ZLTextPosition position = bookmark.getPosition();
+ statement.bindLong(7, position.ParagraphIndex);
+ statement.bindLong(8, position.WordIndex);
+ statement.bindLong(9, position.CharIndex);
+
+ if (statement == myInsertBookmarkStatement) {
+ return statement.executeInsert();
+ } else {
+ final long id = bookmark.getId();
+ statement.bindLong(10, id);
+ statement.execute();
+ return id;
+ }
+ }
+
+ private SQLiteStatement myDeleteBookmarkStatement;
+ protected void deleteBookmark(Bookmark bookmark) {
+ if (myDeleteBookmarkStatement == null) {
+ myDeleteBookmarkStatement = myDatabase.compileStatement(
+ "DELETE FROM Bookmarks WHERE bookmark_id = ?"
);
}
- executeAsATransaction(new Runnable() {
- public void run() {
- myDeleteBookmarksStatement.bindLong(1, bookId);
- myDeleteBookmarksStatement.execute();
- if (list.isEmpty()) {
- return;
- }
- myInsertBookmarkStatement.bindLong(1, bookId);
- for (Bookmark bookmark : list) {
- myInsertBookmarkStatement.bindString(2, bookmark.getText());
- bindDate(myInsertBookmarkStatement, 3, bookmark.getTime(Bookmark.CREATION));
- bindDate(myInsertBookmarkStatement, 4, bookmark.getTime(Bookmark.MODIFICATION));
- bindDate(myInsertBookmarkStatement, 5, bookmark.getTime(Bookmark.ACCESS));
- myInsertBookmarkStatement.bindLong(6, bookmark.getAccessCount());
- final ZLTextPosition position = bookmark.getPosition();
- myInsertBookmarkStatement.bindLong(7, position.ParagraphIndex);
- myInsertBookmarkStatement.bindLong(8, position.WordIndex);
- myInsertBookmarkStatement.bindLong(9, position.CharIndex);
- myInsertBookmarkStatement.execute();
- }
- }
- });
+ myDeleteBookmarkStatement.bindLong(1, bookmark.getId());
+ myDeleteBookmarkStatement.execute();
}
private void createTables() {
@@ -772,6 +838,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
private void updateTables5() {
myDatabase.execSQL(
"CREATE TABLE Bookmarks(" +
+ "bookmark_id INTEGER PRIMARY KEY," +
"book_id INTEGER NOT NULL REFERENCES Books(book_id)," +
"bookmark_text TEXT NOT NULL," +
"creation_time INTEGER NOT NULL," +
@@ -785,23 +852,4 @@ final class SQLiteBooksDatabase extends BooksDatabase {
private void updateTables6() {
}
-
- protected void listBookmarks(long bookId, List list) {
- Cursor cursor = myDatabase.rawQuery(
- "SELECT bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char FROM Bookmarks WHERE book_id = ?", new String[] { "" + bookId }
- );
- while (cursor.moveToNext()) {
- list.add(createBookmark(
- cursor.getString(0),
- getDate(cursor, 1),
- getDate(cursor, 2),
- getDate(cursor, 3),
- (int)cursor.getLong(4),
- (int)cursor.getLong(5),
- (int)cursor.getLong(6),
- (int)cursor.getLong(7)
- ));
- }
- cursor.close();
- }
}
diff --git a/src/org/geometerplus/fbreader/fbreader/BookTextView.java b/src/org/geometerplus/fbreader/fbreader/BookTextView.java
index 8776e5406..00a145470 100644
--- a/src/org/geometerplus/fbreader/fbreader/BookTextView.java
+++ b/src/org/geometerplus/fbreader/fbreader/BookTextView.java
@@ -29,6 +29,7 @@ import org.geometerplus.zlibrary.core.options.*;
import org.geometerplus.zlibrary.core.config.ZLConfig;
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
import org.geometerplus.zlibrary.text.model.ZLTextModel;
+import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.text.view.impl.*;
public class BookTextView extends FBView {
diff --git a/src/org/geometerplus/fbreader/fbreader/FBReader.java b/src/org/geometerplus/fbreader/fbreader/FBReader.java
index 1c7344118..399956ead 100644
--- a/src/org/geometerplus/fbreader/fbreader/FBReader.java
+++ b/src/org/geometerplus/fbreader/fbreader/FBReader.java
@@ -33,6 +33,7 @@ import org.geometerplus.zlibrary.core.view.ZLViewWidget;
import org.geometerplus.zlibrary.text.model.ZLTextModel;
import org.geometerplus.zlibrary.text.view.ZLTextView;
+import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.text.hyphenation.ZLTextHyphenator;
import org.geometerplus.fbreader.bookmodel.BookModel;
@@ -125,10 +126,10 @@ public final class FBReader extends ZLApplication {
);
}
- public void openBook(final Book book) {
+ public void openBook(final Book book, final ZLTextPosition position) {
ZLDialogManager.Instance().wait("loadingBook", new Runnable() {
public void run() {
- openBookInternal(book);
+ openBookInternal(book, position);
}
});
}
@@ -206,7 +207,7 @@ public final class FBReader extends ZLApplication {
FootnoteView.clearCaches();
}
- void openBookInternal(Book book) {
+ void openBookInternal(Book book, ZLTextPosition position) {
clearTextCaches();
if (book != null) {
@@ -222,6 +223,9 @@ public final class FBReader extends ZLApplication {
ZLTextHyphenator.Instance().load(book.getLanguage());
BookTextView.setModel(Model.BookTextModel, fileName);
BookTextView.setCaption(book.getTitle());
+ if (position != null) {
+ BookTextView.gotoPosition(position);
+ }
FootnoteView.setModel(null);
FootnoteView.setCaption(book.getTitle());
Library.Instance().addBookToRecentList(book);
@@ -243,13 +247,13 @@ main:
if (f == null) {
continue;
}
- book = Book.getBook(f);
+ book = Book.getByFile(f);
if (book != null) {
break;
}
if (f.isArchive()) {
for (ZLFile child : f.children()) {
- book = Book.getBook(child);
+ book = Book.getByFile(child);
if (book != null) {
break main;
}
@@ -257,7 +261,7 @@ main:
}
}
if (book != null) {
- openBookInternal(book);
+ openBookInternal(book, null);
}
}
});
diff --git a/src/org/geometerplus/fbreader/library/Book.java b/src/org/geometerplus/fbreader/library/Book.java
index adc848337..4683b4f0c 100644
--- a/src/org/geometerplus/fbreader/library/Book.java
+++ b/src/org/geometerplus/fbreader/library/Book.java
@@ -27,7 +27,32 @@ import org.geometerplus.zlibrary.core.filesystem.*;
import org.geometerplus.fbreader.formats.*;
public class Book {
- public static Book getBook(ZLFile bookFile) {
+ public static Book getById(long bookId) {
+ final Book book = BooksDatabase.Instance().loadBook(bookId);
+ if (book == null) {
+ return null;
+ }
+ book.loadLists();
+
+ final ZLPhysicalFile physicalFile = book.File.getPhysicalFile();
+ if (physicalFile == null) {
+ return book;
+ }
+ if (!physicalFile.exists()) {
+ return null;
+ }
+
+ FileInfoSet fileInfos = new FileInfoSet();
+ fileInfos.load(physicalFile);
+ if (fileInfos.check(physicalFile)) {
+ return book;
+ }
+ fileInfos.save();
+
+ return book.readMetaInfo() ? book : null;
+ }
+
+ public static Book getByFile(ZLFile bookFile) {
if (bookFile == null) {
return null;
}
@@ -37,25 +62,22 @@ public class Book {
return null;
}
- final Book book = new Book(bookFile, true);
+ Book book = BooksDatabase.Instance().loadBook(bookFile.getPath());
+ if (book != null) {
+ book.loadLists();
+ }
FileInfoSet fileInfos = new FileInfoSet();
fileInfos.load(physicalFile);
- if (fileInfos.check(physicalFile) && book.myIsSaved) {
+ if (fileInfos.check(physicalFile) && (book != null)) {
return book;
}
fileInfos.save();
- final FormatPlugin plugin = PluginCollection.instance().getPlugin(bookFile);
- if ((plugin == null) || !plugin.readMetaInfo(book)) {
- return null;
+ if (book == null) {
+ book = new Book(bookFile);
}
-
- String title = book.getTitle();
- if ((title == null) || (title.length() == 0)) {
- book.setTitle(bookFile.getName(true));
- }
- return book;
+ return book.readMetaInfo() ? book : null;
}
public final ZLFile File;
@@ -80,20 +102,28 @@ public class Book {
myIsSaved = true;
}
- Book(ZLFile file, boolean createFromDatabase) {
+ Book(ZLFile file) {
+ myId = -1;
File = file;
- if (createFromDatabase) {
- final BooksDatabase database = BooksDatabase.Instance();
- myId = database.loadBook(this);
- if (myId >= 0) {
- myAuthors = database.loadAuthors(myId);
- myTags = database.loadTags(myId);
- mySeriesInfo = database.loadSeriesInfo(myId);
- myIsSaved = true;
- }
- } else {
- myId = -1;
+ }
+
+ boolean readMetaInfo() {
+ final FormatPlugin plugin = PluginCollection.instance().getPlugin(File);
+ if ((plugin == null) || !plugin.readMetaInfo(this)) {
+ return false;
}
+ if ((myTitle == null) || (myTitle.length() == 0)) {
+ setTitle(File.getName(true));
+ }
+ return true;
+ }
+
+ private void loadLists() {
+ final BooksDatabase database = BooksDatabase.Instance();
+ myAuthors = database.loadAuthors(myId);
+ myTags = database.loadTags(myId);
+ mySeriesInfo = database.loadSeriesInfo(myId);
+ myIsSaved = true;
}
public List authors() {
diff --git a/src/org/geometerplus/fbreader/library/Bookmark.java b/src/org/geometerplus/fbreader/library/Bookmark.java
index 95205bc28..b9b5ecae5 100644
--- a/src/org/geometerplus/fbreader/library/Bookmark.java
+++ b/src/org/geometerplus/fbreader/library/Bookmark.java
@@ -19,35 +19,65 @@
package org.geometerplus.fbreader.library;
-import java.util.Date;
+import java.util.*;
-import org.geometerplus.zlibrary.text.view.impl.ZLTextPosition;
+import org.geometerplus.zlibrary.text.view.ZLTextPosition;
public class Bookmark {
public final static int CREATION = 0;
public final static int MODIFICATION = 1;
public final static int ACCESS = 2;
+ public final static int LATEST = 3;
+ public static List bookmarks() {
+ return BooksDatabase.Instance().listAllBookmarks();
+ }
+
+ private long myId;
+ private long myBookId;
private String myText;
private final Date myCreationDate;
private Date myModificationDate;
private Date myAccessDate;
private int myAccessCount;
+ private Date myLatestDate;
private final ZLTextPosition myPosition;
- Bookmark(String text, Date creationDate, Date modificationDate, Date accessDate, int accessCount, int paragraphIndex, int wordIndex, int charIndex) {
+ private boolean myIsChanged;
+
+ Bookmark(long id, long bookId, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCount, int paragraphIndex, int wordIndex, int charIndex) {
+ myId = id;
+ myBookId = bookId;
myText = text;
myCreationDate = creationDate;
myModificationDate = modificationDate;
- myAccessDate = accessDate;
+ myLatestDate = (modificationDate != null) ? modificationDate : creationDate;
+ if (accessDate != null) {
+ myAccessDate = accessDate;
+ if (myLatestDate.compareTo(accessDate) < 0) {
+ myLatestDate = accessDate;
+ }
+ }
myAccessCount = accessCount;
myPosition = new ZLTextPosition(paragraphIndex, wordIndex, charIndex);
+ myIsChanged = false;
}
- public Bookmark(String text, ZLTextPosition position) {
+ public Bookmark(Book book, String text, ZLTextPosition position) {
+ myId = -1;
+ myBookId = book.getId();
myText = text;
myCreationDate = new Date();
myPosition = position;
+ myIsChanged = true;
+ }
+
+ public long getId() {
+ return myId;
+ }
+
+ public long getBookId() {
+ return myBookId;
}
public String getText() {
@@ -67,6 +97,8 @@ public class Bookmark {
return myModificationDate;
case ACCESS:
return myAccessDate;
+ case LATEST:
+ return myLatestDate;
}
}
@@ -74,17 +106,44 @@ public class Bookmark {
return myAccessCount;
}
- boolean setText(String text) {
+ public void setText(String text) {
if (!text.equals(myText)) {
myText = text;
myModificationDate = new Date();
- return true;
+ myLatestDate = myModificationDate;
+ myIsChanged = true;
}
- return false;
}
- void onAccess() {
+ public void onOpen() {
myAccessDate = new Date();
++myAccessCount;
+ myLatestDate = myAccessDate;
+ myIsChanged = true;
+ }
+
+ public void save() {
+ if (myIsChanged) {
+ myId = BooksDatabase.Instance().saveBookmark(this);
+ myIsChanged = false;
+ }
+ }
+
+ public void delete() {
+ if (myId != -1) {
+ BooksDatabase.Instance().deleteBookmark(this);
+ }
+ }
+
+ public static class ByTimeComparator implements Comparator {
+ public int compare(Bookmark bm0, Bookmark bm1) {
+ return bm1.getTime(LATEST).compareTo(bm0.getTime(LATEST));
+ }
+ }
+
+ public static class ByPositionComparator implements Comparator {
+ public int compare(Bookmark bm0, Bookmark bm1) {
+ return bm0.getPosition().compareTo(bm1.getPosition());
+ }
}
}
diff --git a/src/org/geometerplus/fbreader/library/BookmarkList.java b/src/org/geometerplus/fbreader/library/BookmarkList.java
deleted file mode 100644
index 37cb2afe0..000000000
--- a/src/org/geometerplus/fbreader/library/BookmarkList.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 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.fbreader.library;
-
-import java.util.LinkedList;
-
-import org.geometerplus.zlibrary.text.view.impl.ZLTextPosition;
-import org.geometerplus.zlibrary.text.view.impl.ZLTextViewImpl;
-
-public class BookmarkList extends LinkedList {
- private final Book myBook;
- private boolean myIsChanged;
-
- public BookmarkList(Book book) {
- myBook = book;
- BooksDatabase.Instance().listBookmarks(book.getId(), this);
- }
-
- public void addNewBookmark(String text, ZLTextPosition position) {
- add(0, new Bookmark(text, position));
- myIsChanged = true;
- }
-
- public void removeBookmark(int index) {
- remove(index);
- myIsChanged = true;
- }
-
- public void setBookmarkText(int index, String text) {
- if (get(index).setText(text)) {
- myIsChanged = true;
- }
- }
-
- public void gotoBookmark(int index, ZLTextViewImpl view) {
- myIsChanged = true;
- final Bookmark bookmark = get(index);
- bookmark.onAccess();
- view.gotoPosition(bookmark.getPosition());
- }
-
- public void save() {
- if (!myIsChanged) {
- return;
- }
- BooksDatabase.Instance().saveBookmarks(myBook.getId(), this);
- myIsChanged = false;
- }
-}
diff --git a/src/org/geometerplus/fbreader/library/BooksDatabase.java b/src/org/geometerplus/fbreader/library/BooksDatabase.java
index 9a3be2bb1..1ba5b2db4 100644
--- a/src/org/geometerplus/fbreader/library/BooksDatabase.java
+++ b/src/org/geometerplus/fbreader/library/BooksDatabase.java
@@ -49,7 +49,8 @@ public abstract class BooksDatabase {
protected abstract Map listBooks();
protected abstract void executeAsATransaction(Runnable actions);
- protected abstract long loadBook(Book book);
+ protected abstract Book loadBook(long bookId);
+ protected abstract Book loadBook(String fileName);
protected abstract List loadAuthors(long bookId);
protected abstract List loadTags(long bookId);
protected abstract SeriesInfo loadSeriesInfo(long bookId);
@@ -74,10 +75,12 @@ public abstract class BooksDatabase {
protected abstract List listRecentBookIds();
protected abstract void saveRecentBookIds(final List ids);
- protected Bookmark createBookmark(String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, int paragraphIndex, int wordIndex, int charIndex) {
- return new Bookmark(text, creationDate, modificationDate, accessDate, accessCounter, paragraphIndex, wordIndex, charIndex);
+ protected Bookmark createBookmark(long id, long bookId, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, int paragraphIndex, int wordIndex, int charIndex) {
+ return new Bookmark(id, bookId, text, creationDate, modificationDate, accessDate, accessCounter, paragraphIndex, wordIndex, charIndex);
}
- protected abstract void listBookmarks(long bookId, List list);
- protected abstract void saveBookmarks(long bookId, List list);
+ protected abstract List listBookmarks(long bookId);
+ protected abstract List listAllBookmarks();
+ protected abstract long saveBookmark(Bookmark bookmark);
+ protected abstract void deleteBookmark(Bookmark bookmark);
}
diff --git a/src/org/geometerplus/fbreader/library/Library.java b/src/org/geometerplus/fbreader/library/Library.java
index 1b8b76298..9053e53c6 100644
--- a/src/org/geometerplus/fbreader/library/Library.java
+++ b/src/org/geometerplus/fbreader/library/Library.java
@@ -25,8 +25,6 @@ import java.util.*;
import org.geometerplus.zlibrary.core.filesystem.*;
import org.geometerplus.zlibrary.core.library.ZLibrary;
-import org.geometerplus.fbreader.formats.*;
-
public final class Library {
private static Library ourInstance;
@@ -76,18 +74,11 @@ public final class Library {
Book book = saved.get(bookFile.getPath());
if (book == null) {
doReadMetaInfo = true;
- book = new Book(bookFile, false);
+ book = new Book(bookFile);
}
- if (doReadMetaInfo) {
- final FormatPlugin plugin = PluginCollection.instance().getPlugin(book.File);
- if ((plugin == null) || !plugin.readMetaInfo(book)) {
- return null;
- }
- String title = book.getTitle();
- if ((title == null) || (title.length() == 0)) {
- book.setTitle(bookFile.getName(true));
- }
+ if (doReadMetaInfo && !book.readMetaInfo()) {
+ return null;
}
return book;
}
diff --git a/src/org/geometerplus/zlibrary/core/html/own/ZLOwnHtmlParser.java b/src/org/geometerplus/zlibrary/core/html/own/ZLOwnHtmlParser.java
index 28b0d72e0..2a0b60036 100644
--- a/src/org/geometerplus/zlibrary/core/html/own/ZLOwnHtmlParser.java
+++ b/src/org/geometerplus/zlibrary/core/html/own/ZLOwnHtmlParser.java
@@ -95,7 +95,7 @@ final class ZLOwnHtmlParser {
if (index > 0) {
int startIndex;
for (startIndex = description.indexOf("=", index) + 1;
- !CharacterUtil.isLetter(description.charAt(startIndex));
+ !Character.isLetter(description.charAt(startIndex));
startIndex++) {
}
if (startIndex > 0) {
diff --git a/src/org/geometerplus/zlibrary/core/util/CharacterUtil.java b/src/org/geometerplus/zlibrary/core/util/ZLCharacterUtil.java
similarity index 70%
rename from src/org/geometerplus/zlibrary/core/util/CharacterUtil.java
rename to src/org/geometerplus/zlibrary/core/util/ZLCharacterUtil.java
index ea9a35b06..b19f77468 100644
--- a/src/org/geometerplus/zlibrary/core/util/CharacterUtil.java
+++ b/src/org/geometerplus/zlibrary/core/util/ZLCharacterUtil.java
@@ -19,7 +19,7 @@
package org.geometerplus.zlibrary.core.util;
-public abstract class CharacterUtil {
+public abstract class ZLCharacterUtil {
public static boolean isLetter(char ch) {
return
(('a' <= ch) && (ch <= 'z')) ||
@@ -37,27 +37,4 @@ public abstract class CharacterUtil {
// cyrillic YO & yo
(ch == 0x401) || (ch == 0x451);
}
-
- public static char toLowerCase(char ch) {
- if (ch < 'A') return ch;
- if (ch <= 'Z') return (char)(ch + 'a' - 'A');
-
- // latin1
- if (ch < 0xC0) return ch;
- if (ch == 0xD7) return ch;
- if (ch <= 0xDE) return (char)(ch + 0x20);
-
- // extended latin1
- if (ch < 0x100) return ch;
- if (ch <= 0x178) return ((ch & 0x01) == 0x01) ? ch : (char)(ch + 1);
-
- // cyrillic
- if (ch < 0x410) return ch;
- if (ch <= 0x42F) return (char)(ch + 0x20);
-
- // cyrillic yo
- if (ch == 0x401) return 0x451;
-
- return ch;
- }
}
diff --git a/src/org/geometerplus/zlibrary/text/hyphenation/ZLTextHyphenator.java b/src/org/geometerplus/zlibrary/text/hyphenation/ZLTextHyphenator.java
index 31112fdfc..20771aeb6 100644
--- a/src/org/geometerplus/zlibrary/text/hyphenation/ZLTextHyphenator.java
+++ b/src/org/geometerplus/zlibrary/text/hyphenation/ZLTextHyphenator.java
@@ -55,9 +55,9 @@ public abstract class ZLTextHyphenator {
pattern[0] = ' ';
for (int i = 0, j = word.Offset; i < len; ++i, ++j) {
char symbol = data[j];
- if (CharacterUtil.isLetter(symbol)) {
+ if (ZLCharacterUtil.isLetter(symbol)) {
isLetter[i] = true;
- pattern[i + 1] = CharacterUtil.toLowerCase(symbol);
+ pattern[i + 1] = Character.toLowerCase(symbol);
} else {
pattern[i + 1] = ' ';
}
diff --git a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextPosition.java b/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java
similarity index 76%
rename from src/org/geometerplus/zlibrary/text/view/impl/ZLTextPosition.java
rename to src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java
index 889a4329b..99067f4d2 100644
--- a/src/org/geometerplus/zlibrary/text/view/impl/ZLTextPosition.java
+++ b/src/org/geometerplus/zlibrary/text/view/ZLTextPosition.java
@@ -17,9 +17,11 @@
* 02110-1301, USA.
*/
-package org.geometerplus.zlibrary.text.view.impl;
+package org.geometerplus.zlibrary.text.view;
-public final class ZLTextPosition {
+import org.geometerplus.zlibrary.text.view.impl.ZLTextWordCursor;
+
+public final class ZLTextPosition implements Comparable {
public int ParagraphIndex;
public int WordIndex;
public int CharIndex;
@@ -47,5 +49,15 @@ public final class ZLTextPosition {
(ParagraphIndex == cursor.getParagraphCursor().Index) &&
(WordIndex == cursor.getWordIndex()) &&
(CharIndex == cursor.getCharIndex());
- }
+ }
+
+ public int compareTo(ZLTextPosition position) {
+ if (ParagraphIndex != position.ParagraphIndex) {
+ return ParagraphIndex - position.ParagraphIndex;
+ }
+ if (WordIndex != position.WordIndex) {
+ return WordIndex - position.WordIndex;
+ }
+ return CharIndex - position.CharIndex;
+ }
}
diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
index 1338ebc32..c29d75286 100644
--- a/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
+++ b/src/org/geometerplus/zlibrary/text/view/ZLTextView.java
@@ -39,6 +39,8 @@ public abstract class ZLTextView extends ZLView {
public abstract void setModel(ZLTextModel model);
+ public abstract void gotoPosition(ZLTextPosition position);
+
public abstract void scrollPage(boolean forward, int scrollingMode, int value);
public abstract int search(String text, boolean ignoreCase, boolean wholeText, boolean backward, boolean thisSectionOnly);