blob: b949176c8c25993e99fb9836b3ec8e16c4e18971 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.contacts.activities;
import com.android.contacts.ContactLoader;
import com.android.contacts.ContactSaveService;
import com.android.contacts.ContactsActivity;
import com.android.contacts.R;
import com.android.contacts.detail.ContactDetailDisplayUtils;
import com.android.contacts.detail.ContactDetailFragment;
import com.android.contacts.detail.ContactDetailLayoutController;
import com.android.contacts.detail.ContactLoaderFragment;
import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.model.AccountWithDataSet;
import com.android.contacts.util.PhoneCapabilityTester;
import android.app.ActionBar;
import android.app.Fragment;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.CheckBox;
import android.widget.Toast;
import java.util.ArrayList;
public class ContactDetailActivity extends ContactsActivity {
private static final String TAG = "ContactDetailActivity";
/**
* Boolean intent key that specifies whether pressing the "up" affordance in this activity
* should cause it to finish itself or launch an intent to bring the user back to a specific
* parent activity - the {@link PeopleActivity}.
*/
public static final String INTENT_KEY_FINISH_ACTIVITY_ON_UP_SELECTED =
"finishActivityOnUpSelected";
private ContactLoader.Result mContactData;
private Uri mLookupUri;
private boolean mFinishActivityOnUpSelected;
private ContactDetailLayoutController mContactDetailLayoutController;
private ContactLoaderFragment mLoaderFragment;
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
// This activity must not be shown. We have to select the contact in the
// PeopleActivity instead ==> Create a forward intent and finish
final Intent originalIntent = getIntent();
Intent intent = new Intent();
intent.setAction(originalIntent.getAction());
intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
intent.setFlags(
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_FORWARD_RESULT
| Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setClass(this, PeopleActivity.class);
startActivity(intent);
finish();
return;
}
mFinishActivityOnUpSelected = getIntent().getBooleanExtra(
INTENT_KEY_FINISH_ACTIVITY_ON_UP_SELECTED, false);
setContentView(R.layout.contact_detail_activity);
mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
getFragmentManager(), findViewById(R.id.contact_detail_container),
mContactDetailFragmentListener);
// We want the UP affordance but no app icon.
// Setting HOME_AS_UP, SHOW_TITLE and clearing SHOW_HOME does the trick.
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
| ActionBar.DISPLAY_SHOW_HOME);
actionBar.setTitle("");
}
Log.i(TAG, getIntent().getData().toString());
}
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof ContactLoaderFragment) {
mLoaderFragment = (ContactLoaderFragment) fragment;
mLoaderFragment.setListener(mLoaderFragmentListener);
mLoaderFragment.loadUri(getIntent().getData());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.star, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
ViewGroup starredContainer = (ViewGroup) getLayoutInflater().inflate(
R.layout.favorites_star, null, false);
final CheckBox starredView = (CheckBox) starredContainer.findViewById(R.id.star);
starredView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Toggle "starred" state
// Make sure there is a contact
if (mLookupUri != null) {
Intent intent = ContactSaveService.createSetStarredIntent(
ContactDetailActivity.this, mLookupUri, starredView.isChecked());
ContactDetailActivity.this.startService(intent);
}
}
});
// If there is contact data, update the starred state
if (mContactData != null) {
ContactDetailDisplayUtils.setStarred(mContactData, starredView);
}
starredMenuItem.setActionView(starredContainer);
return true;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// First check if the {@link ContactLoaderFragment} can handle the key
if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
// Otherwise find the correct fragment to handle the event
FragmentKeyListener mCurrentFragment = mContactDetailLayoutController.getCurrentPage();
if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
// In the last case, give the key event to the superclass.
return super.onKeyDown(keyCode, event);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mContactDetailLayoutController != null) {
mContactDetailLayoutController.onSaveInstanceState(outState);
}
}
private final ContactLoaderFragmentListener mLoaderFragmentListener =
new ContactLoaderFragmentListener() {
@Override
public void onContactNotFound() {
finish();
}
@Override
public void onDetailsLoaded(final ContactLoader.Result result) {
if (result == null) {
return;
}
// Since {@link FragmentTransaction}s cannot be done in the onLoadFinished() of the
// {@link LoaderCallbacks}, then post this {@link Runnable} to the {@link Handler}
// on the main thread to execute later.
mHandler.post(new Runnable() {
@Override
public void run() {
// If the activity is destroyed (or will be destroyed soon), don't update the UI
if (isFinishing()) {
return;
}
mContactData = result;
mLookupUri = result.getLookupUri();
invalidateOptionsMenu();
setupTitle();
mContactDetailLayoutController.setContactData(mContactData);
}
});
}
@Override
public void onEditRequested(Uri contactLookupUri) {
Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
intent.putExtra(
ContactEditorActivity.INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
// Don't finish the detail activity after launching the editor because when the
// editor is done, we will still want to show the updated contact details using
// this activity.
startActivity(intent);
}
@Override
public void onDeleteRequested(Uri contactUri) {
ContactDeletionInteraction.start(ContactDetailActivity.this, contactUri, true);
}
};
/**
* Setup the activity title and subtitle with contact name and company.
*/
private void setupTitle() {
CharSequence displayName = ContactDetailDisplayUtils.getDisplayName(this, mContactData);
String company = ContactDetailDisplayUtils.getCompany(this, mContactData);
ActionBar actionBar = getActionBar();
actionBar.setTitle(displayName);
actionBar.setSubtitle(company);
if (!TextUtils.isEmpty(displayName) &&
AccessibilityManager.getInstance(this).isEnabled()) {
View decorView = getWindow().getDecorView();
decorView.setContentDescription(displayName);
decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
}
private final ContactDetailFragment.Listener mContactDetailFragmentListener =
new ContactDetailFragment.Listener() {
@Override
public void onItemClicked(Intent intent) {
if (intent == null) {
return;
}
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "No activity found for intent: " + intent);
}
}
@Override
public void onCreateRawContactRequested(
ArrayList<ContentValues> values, AccountWithDataSet account) {
Toast.makeText(ContactDetailActivity.this, R.string.toast_making_personal_copy,
Toast.LENGTH_LONG).show();
Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
ContactDetailActivity.this, values, account,
ContactDetailActivity.class, Intent.ACTION_VIEW);
startService(serviceIntent);
}
};
/**
* This interface should be implemented by {@link Fragment}s within this
* activity so that the activity can determine whether the currently
* displayed view is handling the key event or not.
*/
public interface FragmentKeyListener {
/**
* Returns true if the key down event will be handled by the implementing class, or false
* otherwise.
*/
public boolean handleKeyDown(int keyCode);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (mFinishActivityOnUpSelected) {
finish();
return true;
}
Intent intent = new Intent(this, PeopleActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
}