/*
* Copyright (C) 2010-2011 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.library;
import java.util.*;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.view.*;
import android.widget.*;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.image.ZLImage;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.ui.androidfly.R;
import org.geometerplus.fbreader.Paths;
import org.geometerplus.fbreader.library.Book;
import org.geometerplus.fbreader.library.Library;
import org.geometerplus.fbreader.formats.PluginCollection;
import org.geometerplus.android.util.UIUtil;
public final class FileManager extends BaseActivity {
public static String FILE_MANAGER_PATH = "FileManagerPath";
private String myPath;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (DatabaseInstance == null || LibraryInstance == null) {
finish();
return;
}
FileListAdapter adapter = new FileListAdapter();
setListAdapter(adapter);
myPath = getIntent().getStringExtra(FILE_MANAGER_PATH);
if (myPath == null) {
setTitle(myResource.getResource("fileTree").getValue());
addItem("/", "fileTreeRoot");
addItem(Environment.getExternalStorageDirectory().getPath(), "fileTreeCard");
//hym 改,把flybook 书库放到下面的位置来。方便手指点击,单手操作(dz ,最上面很难点到)。
addItem(Paths.BooksDirectoryOption().getValue(), "fileTreeLibrary");
adapter.notifyDataSetChanged();
} else {
setTitle(myPath);
startUpdate();
}
getListView().setOnCreateContextMenuListener(adapter);
getListView().setTextFilterEnabled(true);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
runItem(((FileListAdapter)getListAdapter()).getItem(position));
}
});
}
private void startUpdate() {
new Thread(
new SmartFilter(ZLFile.createFileByPath(myPath))
).start();
}
@Override
protected void onActivityResult(int requestCode, int returnCode, Intent intent) {
if (requestCode == CHILD_LIST_REQUEST && returnCode == RESULT_DO_INVALIDATE_VIEWS) {
if (myPath != null) {
((FileListAdapter)getListAdapter()).clear();
startUpdate();
}
getListView().invalidateViews();
setResult(RESULT_DO_INVALIDATE_VIEWS);
} else if (requestCode == BOOK_INFO_REQUEST) {
getListView().invalidateViews();
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position;
final FileItem fileItem = ((FileListAdapter)getListAdapter()).getItem(position);
final Book book = fileItem.getBook();
if (book != null) {
return onContextItemSelected(item.getItemId(), book);
}
return super.onContextItemSelected(item);
}
@Override
protected void deleteBook(Book book, int mode) {
super.deleteBook(book, mode);
((FileListAdapter)getListAdapter()).deleteFile(book.File);
getListView().invalidateViews();
}
private void runItem(FileItem item) {
final ZLFile file = item.getFile();
final Book book = item.getBook();
if (book != null) {
showBookInfo(book);
} else if (file.isDirectory() || file.isArchive()) {
startActivityForResult(
new Intent(this, FileManager.class)
.putExtra(SELECTED_BOOK_PATH_KEY, mySelectedBookPath)
.putExtra(FILE_MANAGER_PATH, file.getPath()),
CHILD_LIST_REQUEST
);
} else {
UIUtil.showErrorMessage(FileManager.this, "permissionDenied");
}
}
private void addItem(String path, String resourceKey) {
final ZLResource resource = myResource.getResource(resourceKey);
((FileListAdapter)getListAdapter()).add(new FileItem(
ZLFile.createFileByPath(path),
resource.getValue(),
resource.getResource("summary").getValue()
));
}
private boolean isItemSelected(FileItem item) {
if (mySelectedBookPath == null || !item.isSelectable()) {
return false;
}
final ZLFile file = item.getFile();
final String path = file.getPath();
if (mySelectedBookPath.equals(path)) {
return true;
}
String prefix = path;
if (file.isDirectory()) {
if (!prefix.endsWith("/")) {
prefix += '/';
}
} else if (file.isArchive()) {
prefix += ':';
} else {
return false;
}
return mySelectedBookPath.startsWith(prefix);
}
private final class FileListAdapter extends BaseAdapter implements View.OnCreateContextMenuListener {
private List<FileItem> myItems = new ArrayList<FileItem>();
public synchronized void clear() {
myItems.clear();
}
public synchronized void add(FileItem item){
myItems.add(item);
}
public synchronized void deleteFile(ZLFile file) {
for (FileItem item : myItems) {
if (file.equals(item.getFile())) {
myItems.remove(item);
break;
}
}
}
public synchronized int getCount() {
return myItems.size();
}
public synchronized FileItem getItem(int position) {
return myItems.get(position);
}
public long getItemId(int position) {
return position;
}
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
final Book book = getItem(position).getBook();
if (book != null) {
createBookContextMenu(menu, book);
}
}
public View getView(int position, View convertView, ViewGroup parent) {
final FileItem item = getItem(position);
final View view = createView(convertView, parent, item.getName(), item.getSummary());
if (isItemSelected(item)) {
view.setBackgroundColor(0xff555555);
} else {
view.setBackgroundColor(0);
}
final ImageView coverView = getCoverView(view);
final Bitmap coverBitmap = getCoverBitmap(item.getCover());
if (coverBitmap != null) {
coverView.setImageBitmap(coverBitmap);
} else {
coverView.setImageResource(item.getIcon());
}
return view;
}
}
private final class FileItem {
private final ZLFile myFile;
private final String myName;
private final String mySummary;
private final boolean myIsSelectable;
private ZLImage myCover = null;
private boolean myCoverIsInitialized = false;
public FileItem(ZLFile file, String name, String summary) {
myFile = file;
myName = name;
mySummary = summary;
myIsSelectable = false;
}
public FileItem(ZLFile file) {
if (file.isArchive() && file.getPath().endsWith(".fb2.zip")) {
final List<ZLFile> children = file.children();
if (children.size() == 1) {
final ZLFile child = children.get(0);
if (child.getPath().endsWith(".fb2")) {
myFile = child;
myName = file.getLongName();
mySummary = null;
myIsSelectable = true;
return;
}
}
}
myFile = file;
myName = null;
mySummary = null;
myIsSelectable = true;
}
public String getName() {
return myName != null ? myName : myFile.getShortName();
}
public String getSummary() {
if (mySummary != null) {
return mySummary;
}
final Book book = getBook();
if (book != null) {
return book.getTitle();
}
return null;
}
public boolean isSelectable() {
return myIsSelectable;
}
public int getIcon() {
if (getBook() != null) {
return R.drawable.ic_list_library_book;
} else if (myFile.isDirectory()) {
if (myFile.isReadable()) {
return R.drawable.ic_list_library_folder;
} else {
return R.drawable.ic_list_library_permission_denied;
}
} else if (myFile.isArchive()) {
return R.drawable.ic_list_library_zip;
} else {
System.err.println(
"File " + myFile.getPath() +
" that is not a directory, not a book and not an archive " +
"has been found in getIcon()"
);
return R.drawable.ic_list_library_permission_denied;
}
}
public ZLImage getCover() {
if (!myCoverIsInitialized) {
myCoverIsInitialized = true;
myCover = Library.getCover(myFile);
}
return myCover;
}
public ZLFile getFile() {
return myFile;
}
public Book getBook() {
return Book.getByFile(myFile);
}
}
private final class SmartFilter implements Runnable {
private final ZLFile myFile;
public SmartFilter(ZLFile file) {
myFile = file;
}
public void run() {
if (!myFile.isReadable()) {
runOnUiThread(new Runnable() {
public void run() {
UIUtil.showErrorMessage(FileManager.this, "permissionDenied");
}
});
finish();
return;
}
final ArrayList<ZLFile> children = new ArrayList<ZLFile>(myFile.children());
Collections.sort(children, new FileComparator());
for (final ZLFile file : children) {
if (Thread.currentThread().isInterrupted()) {
break;
}
if (file.isDirectory() || file.isArchive() ||
PluginCollection.Instance().getPlugin(file) != null) {
runOnUiThread(new Runnable() {
public void run() {
final FileListAdapter adapter = (FileListAdapter)getListAdapter();
adapter.add(new FileItem(file));
adapter.notifyDataSetChanged();
}
});
}
}
}
}
private static class FileComparator implements Comparator<ZLFile> {
public int compare(ZLFile f0, ZLFile f1) {
return f0.getShortName().compareToIgnoreCase(f1.getShortName());
}
}
}