package yuku.filechooser;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.StyleSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import java.io.File;
import java.util.Arrays;
import yuku.atree.TreeAdapter;
import yuku.atree.TreeNodeIconType;
import yuku.atree.nodes.BaseFileTreeNode;
public class FolderChooserActivity extends Activity {
static final String EXTRA_config = "config"; //$NON-NLS-1$
static final String EXTRA_result = null;
public static Intent createIntent(Context context, FolderChooserConfig config) {
Intent res = new Intent(context, FolderChooserActivity.class);
res.putExtra(EXTRA_config, config);
return res;
}
public static FolderChooserResult obtainResult(Intent data) {
if (data == null) return null;
return data.getParcelableExtra(EXTRA_result);
}
ListView tree;
Button bOk;
TextView lPath;
FolderChooserConfig config;
TreeAdapter adapter;
File selectedDir;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
config = getIntent().getParcelableExtra(EXTRA_config);
Utils.configureTitles(this, config.title, config.subtitle);
setContentView(R.layout.filechooser_activity_folderchooser);
tree = (ListView) findViewById(R.id.filechooser_tree);
bOk = (Button) findViewById(R.id.filechooser_bOk);
lPath = (TextView) findViewById(R.id.filechooser_lPath);
adapter = new TreeAdapter();
tree.setAdapter(adapter);
tree.setOnItemClickListener(tree_itemClick);
perm_writeExt = checkCallingOrSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (perm_writeExt == PackageManager.PERMISSION_GRANTED) {
tree.setOnItemLongClickListener(tree_itemLongClick);
}
bOk.setOnClickListener(bOk_click);
setSelectedDir(null);
if (config.roots == null || config.roots.size() == 0) {
config.roots = Arrays.asList(Environment.getExternalStorageDirectory().getAbsolutePath());
}
File[] children = new File[config.roots.size()];
for (int i = 0; i < config.roots.size(); i++) {
children[i] = new File(config.roots.get(i));
}
FileTreeNode root = new FileTreeNode("root", children);
adapter.setRootVisible(false);
root.setExpanded(true);
if (children.length == 1 && config.expandSingularRoot) {
FileTreeNode childNode = root.getChildAt(0);
childNode.setExpanded(true);
}
if (children.length > 1 && config.expandMultipleRoots) {
for (int i = 0, len = root.getChildCount(); i < len; i++) {
FileTreeNode childNode = root.getChildAt(i);
childNode.setExpanded(true);
}
}
adapter.setRoot(root);
}
private OnItemClickListener tree_itemClick = new OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
FileTreeNode node = (FileTreeNode) adapter.getItem(position);
node.setExpanded(!node.getExpanded());
adapter.notifyDataSetChanged();
setSelectedDir(node.getFile());
}
};
private OnItemLongClickListener tree_itemLongClick = new OnItemLongClickListener() {
@Override public boolean onItemLongClick(AdapterView<?> parent, View v, final int position, long id) {
final FileTreeNode node = (FileTreeNode) adapter.getItem(position);
final File file = node.getFile();
if (!file.isDirectory()) return false;
new AlertDialog.Builder(FolderChooserActivity.this)
.setItems(new String[] {"New folder"}, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface _unused_, int which) {
final Button[] bOk = {null};
final EditText tFolderName = new EditText(FolderChooserActivity.this);
MarginLayoutParams lp = new MarginLayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.leftMargin = lp.topMargin = lp.rightMargin = lp.bottomMargin = (int) (6 * getResources().getDisplayMetrics().density);
tFolderName.setLayoutParams(lp);
tFolderName.setHint("Folder name");
tFolderName.addTextChangedListener(new TextWatcher() {
@Override public void afterTextChanged(Editable s) {
bOk[0].setEnabled(s.toString().trim().length() > 0);
}
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
final AlertDialog dialog = new AlertDialog.Builder(FolderChooserActivity.this)
.setTitle("New folder")
.setView(tFolderName)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
String folderName = tFolderName.getText().toString().trim();
File newDir = new File(file, folderName);
boolean ok = newDir.mkdirs();
if (ok) {
if (node.getExpanded()) {
node.setExpanded(false);
}
node.setExpanded(true);
}
}})
.show();
bOk[0] = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
bOk[0].setEnabled(false);
}
})
.show();
return true;
}
};
OnClickListener bOk_click = new OnClickListener() {
@Override public void onClick(View v) {
if (selectedDir == null) return;
FolderChooserResult result = new FolderChooserResult();
result.selectedFolder = selectedDir.getAbsolutePath();
Intent data = new Intent();
data.putExtra(EXTRA_result, result);
setResult(RESULT_OK, data);
finish();
}
};
private int perm_writeExt;
class FileTreeNode extends BaseFileTreeNode {
private String label;
public FileTreeNode(File file) {
super(file);
}
public FileTreeNode(String label, File[] virtualChildren) {
super(virtualChildren);
this.label = label;
}
@Override public View getView(int position, View convertView, ViewGroup parent, int level, TreeNodeIconType iconType, int[] lines) {
TextView res = (TextView) (convertView != null? convertView: LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_1, null));
res.setPadding((int) ((getResources().getDisplayMetrics().density) * (20 * (level - 1) + 6)), 0, 0, 0);
res.setText(label != null? label: file.getName());
res.setCompoundDrawablesWithIntrinsicBounds(file.isDirectory()? R.drawable.filechooser_folder: R.drawable.filechooser_file, 0, 0, 0);
return res;
}
@Override protected BaseFileTreeNode generateForFile(File file) {
return new FileTreeNode(file);
}
@Override protected boolean showDirectoriesOnly() {
return true;
}
@Override protected boolean showHidden() {
return config.showHidden;
}
}
protected void setSelectedDir(File dir) {
this.selectedDir = dir;
bOk.setEnabled(dir != null);
if (dir != null) {
// display complete path
SpannableStringBuilder sb = new SpannableStringBuilder();
String parent = dir.getParent();
sb.append(parent == null? "": parent + "/");
int sb_len = sb.length();
sb.append(dir.getName());
sb.setSpan(new StyleSpan(Typeface.BOLD), sb_len, sb.length(), 0);
lPath.setText(sb, BufferType.SPANNABLE);
// disable button if not writable
if (config.mustBeWritable && !dir.canWrite()) {
bOk.setEnabled(false);
}
} else {
lPath.setText("");
}
}
}