/*
* Copyright (C) 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.network;
import java.util.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.*;
import android.widget.BaseAdapter;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.language.ZLLanguageUtil;
import org.geometerplus.zlibrary.ui.android.R;
import org.geometerplus.android.util.UIUtil;
import org.geometerplus.fbreader.network.NetworkTree;
import org.geometerplus.fbreader.network.NetworkLibrary;
public class NetworkLibraryActivity extends NetworkBaseActivity {
private NetworkTree myTree;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
}
private void prepareView() {
if (myTree == null) {
myTree = NetworkLibrary.Instance().getTree();
setListAdapter(new LibraryAdapter());
getListView().invalidateViews();
}
}
@Override
public void onResume() {
super.onResume();
tryInitializeNetworkView(this, "loadingNetworkLibrary", new Runnable() {
public void run() {
prepareView();
}
});
}
@Override
public void onDestroy() {
tryStopInitialization();
super.onDestroy();
}
private static Initializator myInitializator;
public static void tryInitializeNetworkView(Activity activity, String key, final Runnable doAfter) {
final NetworkView networkView = NetworkView.Instance();
if (!networkView.isInitialized()) {
if (myInitializator == null) {
myInitializator = new Initializator(activity, key, doAfter);
myInitializator.start();
} else {
myInitializator.setParameters(activity, doAfter);
}
} else if (doAfter != null) {
doAfter.run();
}
}
public static void tryStopInitialization() {
if (!NetworkView.Instance().isInitialized()
&& myInitializator != null) {
myInitializator.setParameters(null, null);
}
}
private static class Initializator extends Handler {
private Activity myActivity;
private String myKey;
private Runnable myDoAfter;
public Initializator(Activity activity, String key, Runnable doAfter) {
myActivity = activity;
myKey = key;
myDoAfter = doAfter;
}
public void setParameters(Activity activity, Runnable doAfter) {
myActivity = activity;
}
final DialogInterface.OnClickListener myListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
Initializator.this.start();
} else if (myActivity != null) {
myActivity.finish();
}
}
};
// run this method only is myActivity != null
private void runInitialization() {
UIUtil.wait(myKey, new Runnable() {
public void run() {
String error = null;
try {
NetworkView.Instance().initialize();
} catch (ZLNetworkException e) {
error = e.getMessage();
}
Initializator.this.end(error);
}
}, myActivity);
}
// run this method only is myActivity != null
private void processResults(String error) {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource boxResource = dialogResource.getResource("networkError");
final ZLResource buttonResource = dialogResource.getResource("button");
new AlertDialog.Builder(myActivity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(error)
.setIcon(0)
.setPositiveButton(buttonResource.getResource("tryAgain").getValue(), myListener)
.setNegativeButton(buttonResource.getResource("cancel").getValue(), myListener)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
myListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
}
})
.create().show();
}
@Override
public void handleMessage(Message message) {
if (myActivity == null) {
return;
} else if (message.what == 0) {
runInitialization(); // run initialization process
} else if (message.obj == null) {
myActivity.startService(new Intent(myActivity.getApplicationContext(), LibraryInitializationService.class));
if (myDoAfter != null) {
myDoAfter.run(); // initialization is complete successfully
}
} else {
processResults((String) message.obj); // handle initialization error
}
}
public void start() {
sendEmptyMessage(0);
}
private void end(String error) {
sendMessage(obtainMessage(1, error));
}
}
private final class LibraryAdapter extends BaseAdapter {
public final int getCount() {
return myTree.subTrees().size()
+ NetworkView.Instance().getSpecialItems().size() + 1;
}
public final NetworkTree getItem(int position) {
List<NetworkTree> specialItems = NetworkView.Instance().getSpecialItems();
int size = specialItems.size();
if (position < size) {
return specialItems.get(position);
}
position -= size;
size = myTree.subTrees().size();
if (position < size) {
return (NetworkTree)myTree.subTrees().get(position);
}
position -= size;
if (position == 0) {
return NetworkView.Instance().getAddCustomCatalogItemTree();
}
return null;
}
public final long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, final ViewGroup parent) {
final NetworkTree tree = getItem(position);
return setupNetworkTreeItemView(convertView, parent, tree);
}
}
protected MenuItem addMenuItem(Menu menu, int index, String resourceKey, int iconId) {
final String label = myResource.getResource("menu").getResource(resourceKey).getValue();
return menu.add(0, index, Menu.NONE, label).setIcon(iconId);
}
private static final int MENU_SEARCH = 1;
private static final int MENU_REFRESH = 2;
private static final int MENU_ADD_CATALOG = 3;
private static final int MENU_LANGUAGE_FILTER = 4;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
addMenuItem(menu, MENU_SEARCH, "networkSearch", R.drawable.ic_menu_networksearch);
addMenuItem(menu, MENU_ADD_CATALOG, "addCustomCatalog", android.R.drawable.ic_menu_add);
addMenuItem(menu, MENU_REFRESH, "refreshCatalogsList", R.drawable.ic_menu_refresh);
addMenuItem(menu, MENU_LANGUAGE_FILTER, "languages", R.drawable.ic_menu_languages);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
final boolean searchInProgress = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY);
menu.findItem(MENU_SEARCH).setEnabled(!searchInProgress);
return true;
}
private void runLanguageFilterDialog() {
final NetworkLibrary library = NetworkLibrary.Instance();
final List<String> allLanguageCodes = library.languageCodes();
Collections.sort(allLanguageCodes, new ZLLanguageUtil.CodeComparator());
final Collection<String> activeLanguageCodes = library.activeLanguageCodes();
final CharSequence[] languageNames = new CharSequence[allLanguageCodes.size()];
final boolean[] checked = new boolean[allLanguageCodes.size()];
for (int i = 0; i < allLanguageCodes.size(); ++i) {
final String code = allLanguageCodes.get(i);
languageNames[i] = ZLLanguageUtil.languageName(code);
checked[i] = activeLanguageCodes.contains(code);
}
final DialogInterface.OnMultiChoiceClickListener listener =
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
checked[which] = isChecked;
}
};
final ZLResource dialogResource = ZLResource.resource("dialog");
final AlertDialog dialog = new AlertDialog.Builder(this)
.setMultiChoiceItems(languageNames, checked, listener)
.setTitle(dialogResource.getResource("languageFilterDialog").getResource("title").getValue())
.setPositiveButton(dialogResource.getResource("button").getResource("ok").getValue(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final TreeSet<String> newActiveCodes = new TreeSet<String>(new ZLLanguageUtil.CodeComparator());
for (int i = 0; i < checked.length; ++i) {
if (checked[i]) {
newActiveCodes.add(allLanguageCodes.get(i));
}
}
library.setActiveLanguageCodes(newActiveCodes);
library.invalidateChildren();
library.synchronize();
NetworkView.Instance().fireModelChanged();
}
})
.create();
dialog.show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SEARCH:
return onSearchRequested();
case MENU_ADD_CATALOG:
AddCustomCatalogItemActions.addCustomCatalog(this);
return true;
case MENU_REFRESH:
refreshCatalogsList();
return true;
case MENU_LANGUAGE_FILTER:
runLanguageFilterDialog();
return true;
default:
return true;
}
}
@Override
public boolean onSearchRequested() {
if (NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY)) {
return false;
}
final NetworkLibrary library = NetworkLibrary.Instance();
startSearch(library.NetworkSearchPatternOption.getValue(), true, null, false);
return true;
}
@Override
public void onModelChanged() {
getListView().invalidateViews();
}
private void refreshCatalogsList() {
final NetworkView view = NetworkView.Instance();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.obj == null) {
view.finishBackgroundUpdate();
} else {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource boxResource = dialogResource.getResource("networkError");
final ZLResource buttonResource = dialogResource.getResource("button");
new AlertDialog.Builder(NetworkLibraryActivity.this)
.setTitle(boxResource.getResource("title").getValue())
.setMessage((String) msg.obj)
.setIcon(0)
.setPositiveButton(buttonResource.getResource("ok").getValue(), null)
.create().show();
}
}
};
UIUtil.wait("updatingCatalogsList", new Runnable() {
public void run() {
String error = null;
try {
view.runBackgroundUpdate(true);
} catch (ZLNetworkException e) {
error = e.getMessage();
}
handler.sendMessage(handler.obtainMessage(0, error));
}
}, this);
}
}