Twidere-App-Android-Twitter.../twidere/src/main/java/org/mariotaku/twidere/fragment/FileSelectorDialogFragment....

320 lines
12 KiB
Java

/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.res.ResourcesCompat;
import android.text.TextUtils.TruncateAt;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ArrayAdapter;
import org.mariotaku.twidere.fragment.iface.ISupportDialogFragmentCallback;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereArrayUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import static android.os.Environment.getExternalStorageDirectory;
public class FileSelectorDialogFragment extends BaseSupportDialogFragment implements LoaderCallbacks<List<File>>,
OnClickListener, OnItemClickListener {
private FilesAdapter mAdapter;
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Bundle args = getArguments();
getLoaderManager().initLoader(0, args, this);
}
@Override
public void onCancel(final DialogInterface dialog) {
super.onCancel(dialog);
final FragmentActivity a = getActivity();
if (a instanceof Callback) {
((Callback) a).onCancelled(this);
}
}
@Override
public void onClick(final DialogInterface dialog, final int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {
final FragmentActivity a = getActivity();
if (isPickDirectory() && a instanceof Callback) {
((Callback) a).onFilePicked(getCurrentDirectory());
}
// dismiss();
break;
}
case DialogInterface.BUTTON_NEGATIVE: {
final FragmentActivity a = getActivity();
if (a instanceof Callback) {
((Callback) a).onCancelled(this);
}
break;
}
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
mAdapter = new FilesAdapter(getActivity());
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setAdapter(mAdapter, this);
builder.setTitle(R.string.pick_file);
builder.setNegativeButton(android.R.string.cancel, this);
if (isPickDirectory()) {
builder.setPositiveButton(android.R.string.ok, this);
}
final AlertDialog dialog = builder.create();
final ListView listView = dialog.getListView();
listView.setOnItemClickListener(this);
return dialog;
}
@Override
public Loader<List<File>> onCreateLoader(final int id, final Bundle args) {
final String[] extensions = args.getStringArray(EXTRA_FILE_EXTENSIONS);
final String path = args.getString(EXTRA_PATH);
File currentDir = path != null ? new File(path) : getExternalStorageDirectory();
if (currentDir == null) {
currentDir = new File("/");
}
getArguments().putString(EXTRA_PATH, currentDir.getAbsolutePath());
return new FilesLoader(getActivity(), currentDir, extensions);
}
@Override
public void onDismiss(final DialogInterface dialog) {
super.onDismiss(dialog);
final FragmentActivity a = getActivity();
if (a instanceof Callback) {
((Callback) a).onDismissed(this);
}
}
@Override
public void onItemClick(final AdapterView<?> view, final View child, final int position, final long id) {
final File file = mAdapter.getItem(position);
if (file == null) return;
if (file.isDirectory()) {
final Bundle args = getArguments();
args.putString(EXTRA_PATH, file.getAbsolutePath());
getLoaderManager().restartLoader(0, args, this);
} else if (file.isFile() && !isPickDirectory()) {
final FragmentActivity a = getActivity();
if (a instanceof Callback) {
((Callback) a).onFilePicked(file);
}
dismiss();
}
}
@Override
public void onLoaderReset(final Loader<List<File>> loader) {
mAdapter.setData(null, null);
}
@Override
public void onLoadFinished(final Loader<List<File>> loader, final List<File> data) {
final File currentDir = getCurrentDirectory();
if (currentDir != null) {
mAdapter.setData(currentDir, data);
if (currentDir.getParent() == null) {
setTitle("/");
} else {
setTitle(currentDir.getName());
}
}
}
private File getCurrentDirectory() {
final Bundle args = getArguments();
final String path = args.getString(EXTRA_PATH);
return path != null ? new File(path) : null;
}
private boolean isPickDirectory() {
final Bundle args = getArguments();
final String action = args != null ? args.getString(EXTRA_ACTION) : null;
return INTENT_ACTION_PICK_DIRECTORY.equals(action);
}
private void setTitle(final CharSequence title) {
final Dialog dialog = getDialog();
if (dialog == null) return;
dialog.setTitle(title);
}
public interface Callback extends ISupportDialogFragmentCallback {
void onFilePicked(File file);
}
private static class FilesAdapter extends ArrayAdapter<File> {
private final int mPadding;
private final int mActionIconColor;
private final Resources mResources;
private File mCurrentPath;
public FilesAdapter(final Context context) {
super(context, android.R.layout.simple_list_item_1);
mResources = context.getResources();
mActionIconColor = !ThemeUtils.isLightTheme(context) ? 0xffffffff : 0xc0333333;
mPadding = (int) (4 * mResources.getDisplayMetrics().density);
}
@Override
public long getItemId(final int position) {
return getItem(position).hashCode();
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final TextView text = (TextView) (view instanceof TextView ? view : view.findViewById(android.R.id.text1));
final File file = getItem(position);
if (file == null || text == null) return view;
if (mCurrentPath != null && file.equals(mCurrentPath.getParentFile())) {
text.setText("..");
} else {
text.setText(file.getName());
}
text.setSingleLine(true);
text.setEllipsize(TruncateAt.MARQUEE);
text.setPadding(mPadding, mPadding, position, mPadding);
final Drawable icon = ResourcesCompat.getDrawable(mResources,
file.isDirectory() ? R.drawable.ic_folder : R.drawable.ic_file, null);
assert icon != null;
icon.mutate();
icon.setColorFilter(mActionIconColor, PorterDuff.Mode.SRC_ATOP);
text.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
return view;
}
public void setData(final File current, final List<File> data) {
mCurrentPath = current;
clear();
if (data != null) {
addAll(data);
}
}
}
private static class FilesLoader extends AsyncTaskLoader<List<File>> {
private final File path;
private final String[] extensions;
private final Pattern extensions_regex;
private static final Comparator<File> NAME_COMPARATOR = new Comparator<File>() {
@Override
public int compare(final File file1, final File file2) {
final Locale loc = Locale.getDefault();
return file1.getName().toLowerCase(loc).compareTo(file2.getName().toLowerCase(loc));
}
};
public FilesLoader(final Context context, final File path, final String[] extensions) {
super(context);
this.path = path;
this.extensions = extensions;
extensions_regex = extensions != null ? Pattern.compile(TwidereArrayUtils.toString(extensions, '|', false),
Pattern.CASE_INSENSITIVE) : null;
}
@Override
public List<File> loadInBackground() {
if (path == null || !path.isDirectory()) return Collections.emptyList();
final File[] listed_files = path.listFiles();
if (listed_files == null) return Collections.emptyList();
final List<File> dirs = new ArrayList<>();
final List<File> files = new ArrayList<>();
for (final File file : listed_files) {
if (!file.canRead() || file.isHidden()) {
continue;
}
if (file.isDirectory()) {
dirs.add(file);
} else if (file.isFile()) {
final String name = file.getName();
final int idx = name.lastIndexOf(".");
if (extensions == null || extensions.length == 0 || idx == -1 || idx > -1
&& extensions_regex.matcher(name.substring(idx + 1)).matches()) {
files.add(file);
}
}
}
Collections.sort(dirs, NAME_COMPARATOR);
Collections.sort(files, NAME_COMPARATOR);
final List<File> list = new ArrayList<>();
final File parent = path.getParentFile();
if (path.getParentFile() != null) {
list.add(parent);
}
list.addAll(dirs);
list.addAll(files);
return list;
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
}
}