net.abcdroid.devfest12.util.actionmodecompat.ActionModeBase.java Source code

Java tutorial

Introduction

Here is the source code for net.abcdroid.devfest12.util.actionmodecompat.ActionModeBase.java

Source

/*
 * Copyright 2012 Google Inc.
 *
 * 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 net.abcdroid.devfest12.util.actionmodecompat;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * A pre-Honeycomb, simple implementation of {@link ActionMode} that simply shows a context menu
 * for the action mode.
 */
class ActionModeBase extends ActionMode implements DialogInterface.OnClickListener {
    private FragmentActivity mActivity;
    private Callback mCallback;
    private MenuInflater mMenuInflater;

    private ContextMenuDialog mDialog;
    private CharSequence mTitle;
    private SimpleMenu mMenu;
    private ArrayAdapter<MenuItem> mMenuItemArrayAdapter;

    ActionModeBase(FragmentActivity activity, Callback callback) {
        mActivity = activity;
        mCallback = callback;
    }

    static ActionModeBase startInternal(final FragmentActivity activity, Callback callback) {
        final ActionModeBase actionMode = new ActionModeBase(activity, callback);
        actionMode.startInternal();
        return actionMode;
    }

    void startInternal() {
        mMenu = new SimpleMenu(mActivity);
        mCallback.onCreateActionMode(this, mMenu);
        mCallback.onPrepareActionMode(this, mMenu);
        mMenuItemArrayAdapter = new ArrayAdapter<MenuItem>(mActivity, android.R.layout.simple_list_item_1,
                android.R.id.text1);
        invalidate();

        // DialogFragment.show() will take care of adding the fragment
        // in a transaction.  We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentManager fm = mActivity.getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        Fragment prev = fm.findFragmentByTag("action_mode_context_menu");
        if (prev != null) {
            ft.remove(prev);
        }
        ft.addToBackStack(null);

        mDialog = new ContextMenuDialog();
        mDialog.mActionModeBase = this;
        mDialog.show(ft, "action_mode_context_menu");
    }

    /**{@inheritDoc}*/
    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
    }

    /**{@inheritDoc}*/
    @Override
    public void setTitle(int resId) {
        mTitle = mActivity.getResources().getString(resId);
    }

    /**{@inheritDoc}*/
    @Override
    public void invalidate() {
        mMenuItemArrayAdapter.clear();
        List<MenuItem> items = new ArrayList<MenuItem>();
        for (int i = 0; i < mMenu.size(); i++) {
            MenuItem item = mMenu.getItem(i);
            if (item.isVisible()) {
                items.add(item);
            }
        }
        Collections.sort(items, new Comparator<MenuItem>() {
            @Override
            public int compare(MenuItem a, MenuItem b) {
                return a.getOrder() - b.getOrder();
            }
        });
        for (MenuItem item : items) {
            mMenuItemArrayAdapter.add(item);
        }
    }

    /**{@inheritDoc}*/
    @Override
    public void finish() {
        if (mDialog != null) {
            mDialog.dismiss();
        }

        mCallback.onDestroyActionMode(this);

        mDialog = null;
        mMenu = null;
        mMenuItemArrayAdapter = null;
        mTitle = null;
    }

    /**{@inheritDoc}*/
    @Override
    public CharSequence getTitle() {
        return mTitle;
    }

    /**{@inheritDoc}*/
    @Override
    public MenuInflater getMenuInflater() {
        if (mMenuInflater == null) {
            mMenuInflater = mActivity.getMenuInflater();
        }
        return mMenuInflater;
    }

    public static void beginMultiChoiceMode(ListView listView, final FragmentActivity activity,
            final MultiChoiceModeListener listener) {
        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
                ActionMode mode = ActionModeBase.start(activity, listener);
                listener.onItemCheckedStateChanged(mode, position, id, true);
                return true;
            }
        });
    }

    @Override
    public void onClick(DialogInterface dialogInterface, int position) {
        mCallback.onActionItemClicked(this, mMenuItemArrayAdapter.getItem(position));
    }

    public static class ContextMenuDialog extends DialogFragment {
        ActionModeBase mActionModeBase;

        public ContextMenuDialog() {
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            if (mActionModeBase == null) {
                // TODO: support orientation changes and avoid this awful hack.
                final Dialog d = new AlertDialog.Builder(getActivity()).create();
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        d.dismiss();
                    }
                });
                return d;
            }

            return new AlertDialog.Builder(getActivity()).setTitle(mActionModeBase.mTitle)
                    .setAdapter(mActionModeBase.mMenuItemArrayAdapter, mActionModeBase).create();
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);
            if (mActionModeBase == null) {
                return;
            }

            mActionModeBase.mDialog = null;
            mActionModeBase.finish();
        }
    }
}