/*
* @copyright 2013 Philip Warner
* @license GNU General Public License
*
* This file is part of Book Catalogue.
*
* Book Catalogue 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 3 of the License, or
* (at your option) any later version.
*
* Book Catalogue 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 Book Catalogue. If not, see <http://www.gnu.org/licenses/>.
*/
package com.eleybourn.bookcatalogue.filechooser;
import java.io.File;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.eleybourn.bookcatalogue.R;
import com.eleybourn.bookcatalogue.compat.BookCatalogueFragment;
import com.eleybourn.bookcatalogue.filechooser.FileLister.FileListerListener;
import com.eleybourn.bookcatalogue.widgets.SimpleListAdapter;
import com.eleybourn.bookcatalogue.widgets.SimpleListAdapter.ViewProvider;
/**
* Fragment to display a simple directory/file browser.
*
* @author pjw
*
* @param <T> Class for file details, used in showing list.
*/
public class FileChooserFragment extends BookCatalogueFragment implements FileListerListener {
private File mRootPath;
protected static final String ARG_ROOT_PATH = "rootPath";
protected static final String ARG_FILE_NAME = "fileName";
protected static final String ARG_LIST = "list";
// Create an empty one in case we are rotated before generated.
protected ArrayList<FileDetails> mList = new ArrayList<FileDetails>();
/**
* Interface that the containing Activity must implement. Called when user changes path.
*
* @author pjw
*/
public interface PathChangedListener {
public void onPathChanged(File root);
}
/** Create a new chooser fragment */
public static FileChooserFragment newInstance(File root, String fileName) {
String path;
// Turn the passed File into a directory
if (root.isDirectory()) {
path = root.getAbsolutePath();
} else {
path = root.getParent();
}
// Build the fragment and save the details
FileChooserFragment frag = new FileChooserFragment();
Bundle args = new Bundle();
args.putString(ARG_ROOT_PATH, path);
args.putString(ARG_FILE_NAME, fileName);
frag.setArguments(args);
return frag;
}
/** Interface for details of files in current directory */
public interface FileDetails extends ViewProvider, Parcelable {
/** Get the underlying File object */
File getFile();
/** Called to fill in the defails of this object in the View provided by the ViewProvider implementation */
public void onSetupView(Context context, int position, View target);
}
/**
* Ensure activity supports event
*/
@Override
public void onAttach(Activity a) {
super.onAttach(a);
checkInstance(a, PathChangedListener.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.file_chooser, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Handle the 'up' item; go to the next directory up
final View root = getView();
((ImageView) root.findViewById(R.id.up)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleUp();
}
});
// If it's new, just build from scratch, otherwise, get the saved directory and list
if (savedInstanceState == null) {
mRootPath = new File(getArguments().getString(ARG_ROOT_PATH));
String fileName = getArguments().getString(ARG_FILE_NAME);
EditText et = (EditText) getView().findViewById(R.id.file_name);
et.setText(fileName);
((TextView) getView().findViewById(R.id.path)).setText(mRootPath.getAbsolutePath());
tellActivityPathChanged();
} else {
mRootPath = new File(savedInstanceState.getString(ARG_ROOT_PATH));
ArrayList<FileDetails> list = savedInstanceState.getParcelableArrayList(ARG_LIST);
this.onGotFileList(mRootPath, list);
}
}
/**
* Convenience method to tell our activity the path has changed.
*/
private void tellActivityPathChanged() {
((PathChangedListener)getActivity()).onPathChanged(mRootPath);
}
/**
* Handle the 'Up' action
*/
private void handleUp() {
String parent = mRootPath.getParent();
if (parent == null) {
Toast.makeText(getActivity(), R.string.no_parent_directory_found, Toast.LENGTH_LONG).show();
return;
}
mRootPath = new File(parent);
tellActivityPathChanged();
}
/**
* Save our root path and list
*/
@Override
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putString(ARG_ROOT_PATH, mRootPath.getAbsolutePath());
state.putParcelableArrayList(ARG_LIST, mList);
}
/**
* List Adapter for FileDetails objects
*
* @author pjw
*/
public class DirectoryAdapter extends SimpleListAdapter<FileDetails> {
boolean series = false;
/**
*
* Pass the parameters directly to the overridden function
*
* @param context
* @param layout
* @param cursor
* @param from
* @param to
*/
public DirectoryAdapter(Context context, int rowViewId, ArrayList<FileDetails> items) {
super(context, rowViewId, items);
}
@Override
protected void onSetupView(FileDetails fileDetails, int position, View target) {
fileDetails.onSetupView(getActivity(), position, target);
}
@Override
protected void onRowClick(FileDetails fileDetails, int position, View v) {
if (fileDetails != null) {
if (fileDetails.getFile().isDirectory()) {
mRootPath = fileDetails.getFile();
tellActivityPathChanged();
} else {
EditText et = (EditText) FileChooserFragment.this.getView().findViewById(R.id.file_name);
et.setText(fileDetails.getFile().getName());
}
}
};
@Override
protected void onListChanged() {
// Just ignore it. They never change.
};
}
/**
* Accessor
*
* @return
*/
public File getSelectedFile() {
EditText et = (EditText) getView().findViewById(R.id.file_name);
return new File(mRootPath.getAbsolutePath() + "/" + et.getText().toString());
}
/**
* Display the list
*
* @param root Root directory
* @param dirs List of FileDetials
*/
@Override
public void onGotFileList(File root, ArrayList<FileDetails> list) {
mRootPath = root;
((TextView) getView().findViewById(R.id.path)).setText(mRootPath.getAbsolutePath());
// Setup and display the list
mList = list;
// We pass 0 as view ID since each item can provide the view id
DirectoryAdapter adapter = new DirectoryAdapter(getActivity(), 0, mList);
ListView lv = ((ListView) getView().findViewById(android.R.id.list));
lv.setAdapter(adapter);
}
}