package com.samsung.sprc.fileselector; import java.io.File; import java.util.ArrayList; import java.util.Collections; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Environment; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; /** * Create the file selection dialog. This class will create a custom dialog for * file selection which can be used to save files. */ public class FileSelector { /** The list of files and folders which you can choose from */ private ListView mFileListView; /** TextView to show current path */ private TextView mCurrentPathTextView; /** EditText for filename or path entry */ private EditText mEditText; /** Button to save/load file */ private Button mSaveLoadButton; /** Cancel Button - close dialog */ private Button mCancelButton; /** Button to create a new folder */ private Button mNewFolderButton; /** Spinner by which to select the file type filtering */ private Spinner mFilterSpinner; /** * Indicates current location in the directory structure displayed in the * dialog. */ private File mCurrentLocation; /** * Default filename placed in EditText field */ private String mDefaultFileName; /** * The file selector dialog. */ private final Dialog mDialog; /** * The SaveLoadClickListener. */ private SaveLoadClickListener mSaveLoadClickListener; private Context mContext; /** Save or Load file listener. */ final OnHandleFileListener mOnHandleFileListener; /** * Constructor that creates the file selector dialog. * * @param context * The current context. * @param operation * LOAD - to load file / SAVE - to save file * @param onHandleFileListener * Notified after pressing the save or load button. * @param defaultFileName * Default filename placed in EditText field * Set to null for none * @param fileFilters * Array with filters */ public FileSelector(final Context context, final FileOperation operation, final OnHandleFileListener onHandleFileListener, final String defaultFileName, final String[] fileFilters) { mContext = context; mOnHandleFileListener = onHandleFileListener; final File sdCard = Environment.getExternalStorageDirectory(); if (sdCard.canRead()) { mCurrentLocation = sdCard; } else { mCurrentLocation = Environment.getRootDirectory(); } mDialog = new Dialog(context); mDialog.setContentView(R.layout.fs_dialog); if(operation == FileOperation.LOAD) { mDialog.setTitle(context.getResources().getString(R.string.fs_openTitle)); } else { mDialog.setTitle(context.getResources().getString(R.string.fs_saveTitle)); } mCurrentPathTextView = (TextView) mDialog.findViewById(R.id.fs_currentPath); mCurrentPathTextView.setText(mCurrentLocation.getAbsolutePath()); mDefaultFileName = defaultFileName == null ? "" : defaultFileName; mEditText = (EditText) mDialog.findViewById(R.id.fs_fileName); mEditText.setText(mDefaultFileName); mEditText.selectAll(); prepareFilterSpinner(fileFilters); prepareFilesList(); setSaveLoadButton(operation); setNewFolderButton(operation); setCancelButton(); mEditText.setOnKeyListener(new View.OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { // If the event is a key-down event on the "enter" button if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { mSaveLoadClickListener.onClick(v); return true; } return false; } }); } /** * This method prepares a filter's list with the String's array * * @param aFilesFilter * - array of filters, the elements of the array will be used as * elements of the spinner */ private void prepareFilterSpinner(String[] filesFilter) { mFilterSpinner = (Spinner) mDialog.findViewById(R.id.fs_fileFilter); if (filesFilter == null || filesFilter.length == 0) { filesFilter = new String[] { FileUtils.FILTER_ALLOW_ALL }; mFilterSpinner.setEnabled(false); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, R.layout.fs_spinner_item, filesFilter); mFilterSpinner.setAdapter(adapter); OnItemSelectedListener onItemSelectedListener = new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> aAdapter, View aView, int arg2, long arg3) { TextView textViewItem = (TextView) aView; String filtr = textViewItem.getText().toString(); makeList(mCurrentLocation, filtr); } @Override public void onNothingSelected(AdapterView<?> arg0) { } }; mFilterSpinner.setOnItemSelectedListener(onItemSelectedListener); } public void changeDirectory(final String filePath) { final File itemLocation = new File(filePath); if (!itemLocation.canRead()) { Toast.makeText(mContext, mContext.getResources().getString(R.string.fs_accessDenied), Toast.LENGTH_SHORT).show(); } else if (itemLocation.isDirectory()) { mCurrentLocation = itemLocation; String fileFilter = ((TextView) mFilterSpinner.getSelectedView()).getText().toString(); makeList(mCurrentLocation, fileFilter); mCurrentPathTextView.setText(mCurrentLocation.getAbsolutePath()); mEditText.setText(mDefaultFileName); mEditText.selectAll(); } else if (itemLocation.isFile()) { mEditText.setText(itemLocation.getName()); } } /** * This method prepares the mFileListView * */ private void prepareFilesList() { mFileListView = (ListView) mDialog.findViewById(R.id.fs_fileList); mFileListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { // Check if "../" item should be added. if (id == 0) { final String parentLocation = mCurrentLocation.getParent(); if (parentLocation != null) { // text == "../" changeDirectory(parentLocation); } else { onItemSelect(parent, position); } } else { onItemSelect(parent, position); } } }); String filtr = mFilterSpinner.getSelectedItem().toString(); makeList(mCurrentLocation, filtr); } /** * The method that fills the list with a directories contents. * * @param location * Indicates the directory whose contents should be displayed in * the dialog. * @param filesFilter * The filter specifies the type of file to be displayed */ private void makeList(final File location, final String filesFilter) { final ArrayList<FileData> fileList = new ArrayList<FileData>(); final String parentLocation = location.getParent(); if (parentLocation != null) { // First item on the list. fileList.add(new FileData("../", FileData.UP_FOLDER)); } File listFiles[] = location.listFiles(); if (listFiles != null) { ArrayList<FileData> fileDataList = new ArrayList<FileData>(); for (int index = 0; index < listFiles.length; index++) { File tempFile = listFiles[index]; if (FileUtils.accept(tempFile, filesFilter)) { int type = tempFile.isDirectory() ? FileData.DIRECTORY : FileData.FILE; fileDataList.add(new FileData(listFiles[index].getName(), type)); } } fileList.addAll(fileDataList); Collections.sort(fileList); } // Fill the list with the contents of fileList. if (mFileListView != null) { FileListAdapter adapter = new FileListAdapter(mContext, fileList); mFileListView.setAdapter(adapter); } } /** * Handle the file list item selection. * * Change the directory on the list or change the name of the saved file if * the user selected a file. * * @param parent * First parameter of the onItemClick() method of * OnItemClickListener. It's a value of text property of the * item. * @param position * Third parameter of the onItemClick() method of * OnItemClickListener. It's the index on the list of the * selected item. */ private void onItemSelect(final AdapterView<?> parent, final int position) { final String itemText = ((FileData) parent.getItemAtPosition(position)).getFileName(); final String itemPath = mCurrentLocation.getAbsolutePath() + File.separator + itemText; changeDirectory(itemPath); } /** * Set button name and click handler for Save or Load button. * * @param operation * Performed file operation. */ private void setSaveLoadButton(final FileOperation operation) { mSaveLoadButton = (Button) mDialog.findViewById(R.id.fs_fileSaveLoad); switch (operation) { case SAVE: mSaveLoadButton.setText(R.string.fs_saveButtonText); break; case LOAD: mSaveLoadButton.setText(R.string.fs_loadButtonText); break; } mSaveLoadClickListener = new SaveLoadClickListener(operation, this, mContext); mSaveLoadButton.setOnClickListener(mSaveLoadClickListener); } /** * Set button visibility and click handler for New folder button. * * @param operation * Performed file operation. */ private void setNewFolderButton(final FileOperation operation) { mNewFolderButton = (Button) mDialog.findViewById(R.id.fs_newFolder); OnClickListener newFolderListener = new OnClickListener() { @Override public void onClick(final View v) { openNewFolderDialog(); } }; switch (operation) { case SAVE: mNewFolderButton.setVisibility(View.VISIBLE); mNewFolderButton.setOnClickListener(newFolderListener); break; case LOAD: mNewFolderButton.setVisibility(View.GONE); break; } } /** Opens a dialog for creating a new folder. */ private void openNewFolderDialog() { AlertDialog.Builder alert = new AlertDialog.Builder(mContext); alert.setTitle(R.string.fs_newFolderButtonText); alert.setMessage(R.string.fs_newFolderDialogMessage); final EditText input = new EditText(mContext); alert.setView(input); alert.setPositiveButton(R.string.fs_createButtonText, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int whichButton) { File file = new File(mCurrentLocation.getAbsolutePath() + File.separator + input.getText().toString()); if (file.mkdir()) { Toast t = Toast.makeText(mContext, R.string.fs_folderCreationOk, Toast.LENGTH_SHORT); t.setGravity(Gravity.CENTER, 0, 0); t.show(); } else { Toast t = Toast.makeText(mContext, R.string.fs_folderCreationError, Toast.LENGTH_SHORT); t.setGravity(Gravity.CENTER, 0, 0); t.show(); } String fileFilter = ((TextView) mFilterSpinner.getSelectedView()).getText().toString(); makeList(mCurrentLocation, fileFilter); } }); alert.show(); } /** Set onClick() event handler for the cancel button. */ private void setCancelButton() { mCancelButton = (Button) mDialog.findViewById(R.id.fs_fileCancel); mCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(final View view) { mDialog.cancel(); } }); } public String getSelectedFileName() { return mEditText.getText().toString().trim(); } public File getCurrentLocation() { return mCurrentLocation; } /** Simple wrapper around the Dialog.show() method. */ public void show() { mDialog.show(); } /** Simple wrapper around the Dialog.dissmiss() method. */ public void dismiss() { mDialog.dismiss(); } }