com.duy.pascal.ui.file.FileExplorerAction.java Source code

Java tutorial

Introduction

Here is the source code for com.duy.pascal.ui.file.FileExplorerAction.java

Source

/*
 *  Copyright (c) 2017 Tran Le Duy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.duy.pascal.ui.file;

import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.content.FileProvider;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.ShareActionProvider;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;

import com.duy.pascal.ui.BuildConfig;
import com.duy.pascal.ui.R;
import com.duy.pascal.ui.autocomplete.completion.util.CodeTemplate;
import com.duy.pascal.ui.common.utils.UIUtils;
import com.duy.pascal.ui.file.listener.OnClipboardPasteFinishListener;
import com.duy.pascal.ui.file.util.FileUtils;
import com.duy.pascal.ui.file.util.MimeTypes;
import com.duy.pascal.ui.file.util.OnCheckedChangeListener;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Jecelyin Peng <jecelyin@gmail.com>
 */

public class FileExplorerAction
        implements OnCheckedChangeListener, ActionMode.Callback, ShareActionProvider.OnShareTargetSelectedListener {
    private final FileExplorerView mView;
    private final Context mContext;
    private final FileClipboard mFileClipboard;
    private final ExplorerContext mExplorerContext;
    private ActionMode mActionMode;
    private List<File> mCheckedList = new ArrayList<>();
    private ShareActionProvider mShareActionProvider;
    private MenuItem mRenameMenu;
    private MenuItem mShareMenu;
    @Nullable
    private Dialog mDialog;

    public FileExplorerAction(Context context, FileExplorerView view, FileClipboard fileClipboard,
            ExplorerContext explorerContext) {
        this.mView = view;
        this.mContext = context;
        this.mFileClipboard = fileClipboard;
        this.mExplorerContext = explorerContext;
    }

    @Override
    public void onCheckedChanged(File file, int position, boolean checked) {
        if (checked) {
            mCheckedList.add(file);
        } else {
            mCheckedList.remove(file);
        }
    }

    @Override
    public void onCheckedChanged(int checkedCount) {
        if (checkedCount > 0) {
            if (mActionMode == null) {
                mActionMode = mView.startActionMode(this);
            }
            mActionMode.setTitle(mContext.getString(R.string.selected_x_items, checkedCount));
        } else {
            if (mActionMode != null) {
                mActionMode.finish();
                mActionMode = null;
            }
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        menu.add(0, R.id.select_all, 0, R.string.select_all).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
        menu.add(0, R.id.cut, 0, R.string.cut).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        menu.add(0, R.id.copy, 0, R.string.copy).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

        MenuItem pasteMenu = menu.add(0, R.id.paste, 0, R.string.paste);
        pasteMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        pasteMenu.setEnabled(mFileClipboard.canPaste());

        mRenameMenu = menu.add(0, R.id.rename, 0, R.string.rename);
        mRenameMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

        mShareMenu = menu.add(0, R.id.share, 0, R.string.share);
        mShareMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        mShareActionProvider = new ShareActionProvider(mContext);
        mShareActionProvider.setOnShareTargetSelectedListener(this);
        MenuItemCompat.setActionProvider(mShareMenu, mShareActionProvider);

        menu.add(0, R.id.delete, 0, R.string.delete).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        mShareMenu.setEnabled(canShare());
        mRenameMenu.setEnabled(mCheckedList.size() == 1);
        return true;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.select_all) {
            if (!item.isChecked()) {
                mView.setSelectAll(true);
                item.setChecked(true);
                item.setTitle(R.string.cancel_select_all);
            } else {
                mView.setSelectAll(false);
            }
        } else if (id == R.id.copy && !mCheckedList.isEmpty()) {
            mFileClipboard.setData(true, mCheckedList);
            destroyActionMode();
        } else if (id == R.id.cut && !mCheckedList.isEmpty()) {
            mFileClipboard.setData(false, mCheckedList);
            destroyActionMode();
        } else if (id == R.id.paste) {
            destroyActionMode();
            mFileClipboard.paste(mContext, mExplorerContext.getCurrentDirectory(),
                    new OnClipboardPasteFinishListener() {
                        @Override
                        public void onFinish(int count, String error) {
                            mFileClipboard.showPasteResult(mContext, count, error);
                        }
                    });
        } else if (id == R.id.rename) {
            doRenameAction();
        } else if (id == R.id.share) {
            shareFile();
        } else if (id == R.id.delete) {
            doDeleteAction();
        } else {
            return false;
        }
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mShareActionProvider.setOnShareTargetSelectedListener(null);
        mShareActionProvider = null;
        mCheckedList.clear();
        mView.setSelectAll(false);
        mRenameMenu = null;
        mShareMenu = null;
        mActionMode = null;
    }

    public void destroy() {
        if (mDialog != null)
            mDialog.cancel();
        destroyActionMode();
    }

    private void destroyActionMode() {
        if (mActionMode != null) {
            mActionMode.finish();
            mActionMode = null;
        }
    }

    private boolean canShare() {
        for (File file : mCheckedList) {
            if (file == null || !file.isFile())
                return false;
        }
        return true;
    }

    private void doRenameAction() {
        if (mCheckedList.size() != 1)
            return;

        final File file = mCheckedList.get(0);
        UIUtils.showInputDialog(mContext, R.string.rename, 0, file.getName(), 0, new UIUtils.OnShowInputCallback() {
            @Override
            public void onConfirm(CharSequence input) {
                if (TextUtils.isEmpty(input)) {
                    return;
                }
                if (file.getName().equals(input)) {
                    destroyActionMode();
                    return;
                }
                File dest = new File(file.getParentFile(), input.toString());
                boolean result = file.renameTo(dest);
                if (!result) {
                    UIUtils.toast(mContext, R.string.rename_fail);
                    return;
                }
                mView.refresh();
                destroyActionMode();
            }
        });
    }

    private void shareFile() {
        if (mCheckedList.isEmpty() || mShareActionProvider == null)
            return;
        try {
            Intent shareIntent = new Intent();
            if (mCheckedList.size() == 1) {
                File file = new File(mCheckedList.get(0).getPath());
                shareIntent.setAction(Intent.ACTION_SEND);
                shareIntent.setType(MimeTypes.getInstance().getMimeType(file.getPath()));

                Uri fileUri;
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
                    fileUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider",
                            file);
                } else {
                    fileUri = Uri.fromFile(file);
                }
                shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
                shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            } else {
                shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);

                ArrayList<Uri> streams = new ArrayList<>();
                for (File file : mCheckedList) {
                    File File = new File(file.getPath());
                    Uri fileUri;
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
                        fileUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider",
                                File);
                    } else {
                        fileUri = Uri.fromFile(File);
                    }
                    streams.add(fileUri);
                }

                shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, streams);
                shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
            mShareActionProvider.setShareIntent(shareIntent);
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }
    }

    private void doDeleteAction() {
        for (File file : mCheckedList) {
            mView.onPrepareDeleteFile(file);
            FileUtils.deleteRecursive(file);
        }
        mView.refresh();
        destroyActionMode();
    }

    @Override
    public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
        destroyActionMode();
        return false;
    }

    public void doCreateFolder(@Nullable final FileActionListener callback) {
        if (mDialog != null && mDialog.isShowing()) {
            mDialog.cancel();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle(R.string.new_folder);
        builder.setView(R.layout.dialog_input);
        mDialog = builder.create();
        mDialog.show();
        final EditText editText = mDialog.findViewById(R.id.edit_input);
        TextInputLayout textInputLayout = mDialog.findViewById(R.id.hint);
        textInputLayout.setHint(mContext.getString(R.string.enter_new_folder_name));

        Button btnOK = mDialog.findViewById(R.id.btn_ok);
        Button btnCancel = mDialog.findViewById(R.id.btn_cancel);
        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDialog.cancel();
            }
        });
        btnOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //get string path of in edit text
                String input = editText.getText().toString();
                if (input.isEmpty()) {
                    editText.setError(mContext.getString(R.string.enter_new_file_name));
                    return;
                }
                final File folder = new File(mExplorerContext.getCurrentDirectory(), input);
                boolean result = folder.mkdirs();
                if (!result) {
                    UIUtils.toast(mContext, R.string.can_not_create_folder);
                    return;
                }
                mView.refresh();
                if (callback != null) {
                    callback.onFileSelected(new File(folder.getPath()));
                }
                destroyActionMode();
                mDialog.cancel();
            }
        });
    }

    public void showDialogCreateFile(@Nullable final FileActionListener callback) {
        if (mDialog != null && mDialog.isShowing()) {
            mDialog.dismiss();
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setView(R.layout.dialog_new_file);

        mDialog = builder.create();
        mDialog.show();

        final EditText editText = mDialog.findViewById(R.id.edit_input);
        View btnOK = mDialog.findViewById(R.id.btn_ok);
        View btnCancel = mDialog.findViewById(R.id.btn_cancel);

        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDialog.cancel();
            }
        });
        btnOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //get string path of in edit text
                String fileName = editText.getText().toString().trim();
                if (!FileManager.acceptPasFile(fileName)) {
                    editText.setError(mContext.getString(R.string.invalid_file_name));
                    return;
                }

                RadioButton isProgram = mDialog.findViewById(R.id.rad_program);
                RadioButton isUnit = mDialog.findViewById(R.id.rad_unit);
                RadioButton isInput = mDialog.findViewById(R.id.rad_inp);

                String template = "";
                if (isInput.isChecked()) {
                    fileName += ".inp";
                } else if (isUnit.isChecked()) {
                    template = CodeTemplate.createUnitTemplate(fileName);
                    fileName += ".pas";
                } else if (isProgram.isChecked()) {
                    template = CodeTemplate.createProgramTemplate(fileName);
                    fileName += ".pas";
                }

                File file = new File(mExplorerContext.getCurrentDirectory(), fileName);
                FileManager fileManager = new FileManager(mContext);
                boolean result = fileManager.createNewFile(file.getPath()) != null;
                if (!result) {
                    editText.setError(mContext.getString(R.string.can_not_create_file));
                    return;
                } else {
                    fileManager.saveFile(file, template);
                }
                if (callback != null) {
                    callback.onFileSelected(new File(file.getPath()));
                }
                mView.refresh();
                destroyActionMode();
                mDialog.cancel();
            }
        });
    }
}