/*
* 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 com.google.android.apps.iosched.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();
}
}
}