Merge "Removing "custom" from filter list when there are not accounts."
diff --git a/res/layout/account_selector_list_item.xml b/res/layout/account_selector_list_item.xml
new file mode 100644
index 0000000..38acfc5
--- /dev/null
+++ b/res/layout/account_selector_list_item.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+>
+ <ImageView android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_centerVertical="true"
+ />
+
+ <TextView android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="6dip"
+ android:layout_toRightOf="@android:id/icon"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <TextView android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_alignLeft="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+</RelativeLayout>
diff --git a/res/menu/actions.xml b/res/menu/actions.xml
index bc537c3..f431a97 100644
--- a/res/menu/actions.xml
+++ b/res/menu/actions.xml
@@ -16,8 +16,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_add"
- android:icon="@drawable/ic_menu_add_contact"
- android:title="@string/menu_newContact"
android:showAsAction="always" />
<item
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 832987e..d92154c 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -24,12 +24,14 @@
<!-- The height of the ScrollingTabWidget -->
<dimen name="tab_height">40dip</dimen>
<dimen name="account_name_height">25dip</dimen>
-
+
<dimen name="contact_shortcut_frame_width">50dip</dimen>
<dimen name="contact_shortcut_frame_height">56dip</dimen>
-
+
<dimen name="aggregation_suggestion_icon_size">40dip</dimen>
+ <dimen name="account_selector_popup_width">400dip</dimen>
+
<!-- Size of the text in the aizy visual scroll control -->
<dimen name="aizy_text_size">13dip</dimen>
<dimen name="aizy_preview_width">80dip</dimen>
diff --git a/src/com/android/contacts/activities/ContactBrowserActivity.java b/src/com/android/contacts/activities/ContactBrowserActivity.java
index a70fbc4..ace768f 100644
--- a/src/com/android/contacts/activities/ContactBrowserActivity.java
+++ b/src/com/android/contacts/activities/ContactBrowserActivity.java
@@ -30,7 +30,9 @@
import com.android.contacts.list.DefaultContactBrowseListFragment;
import com.android.contacts.list.OnContactBrowserActionListener;
import com.android.contacts.list.StrequentContactListFragment;
+import com.android.contacts.model.AccountTypes;
import com.android.contacts.preference.ContactsPreferenceActivity;
+import com.android.contacts.util.AccountsListAdapter;
import com.android.contacts.util.DialogManager;
import com.android.contacts.views.ContactSaveService;
import com.android.contacts.views.detail.ContactDetailFragment;
@@ -51,6 +53,7 @@
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -59,7 +62,12 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageView;
+import android.widget.ListPopupWindow;
import android.widget.Toast;
import java.util.ArrayList;
@@ -112,6 +120,8 @@
private ContactListFilterController mContactListFilterController;
+ private ImageView mAddContactImageView;
+
public ContactBrowserActivity() {
mIntentResolver = new ContactsIntentResolver(this);
mContactListFilterController = new ContactListFilterController(this);
@@ -180,6 +190,15 @@
mActionBarAdapter.setListener(this);
mActionBarAdapter.setContactListFilterController(mContactListFilterController);
// TODO: request may ask for FREQUENT - set the filter accordingly
+ mAddContactImageView = new ImageView(this);
+ mAddContactImageView.setImageResource(R.drawable.ic_menu_add_contact);
+ mAddContactImageView.setContentDescription(getString(R.string.menu_newContact));
+ mAddContactImageView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ createNewContact();
+ }
+ });
}
configureListFragment(true /* from request */);
@@ -585,6 +604,10 @@
MenuInflater inflater = getMenuInflater();
if (mHasActionBar) {
inflater.inflate(R.menu.actions, menu);
+
+ // Change add contact button to button with a custom view
+ final MenuItem addContact = menu.findItem(R.id.menu_add);
+ addContact.setActionView(mAddContactImageView);
return true;
} else if (mRequest.getActionCode() == ContactsRequest.ACTION_DEFAULT ||
mRequest.getActionCode() == ContactsRequest.ACTION_STREQUENT) {
@@ -641,6 +664,35 @@
return false;
}
+ private void createNewContact() {
+ final ArrayList<Account> accounts =
+ AccountTypes.getInstance(this).getAccounts(true);
+ if (accounts.size() <= 1 || mAddContactImageView == null) {
+ // No account to choose or no control to anchor the popup-menu to
+ // ==> just go straight to the editor which will disambig if necessary
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
+ return;
+ }
+
+ final ListPopupWindow popup = new ListPopupWindow(this, null);
+ popup.setWidth(getResources().getDimensionPixelSize(R.dimen.account_selector_popup_width));
+ popup.setAnchorView(mAddContactImageView);
+ final AccountsListAdapter adapter = new AccountsListAdapter(this, true);
+ popup.setAdapter(adapter);
+ popup.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ popup.dismiss();
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ intent.putExtra(Intents.Insert.ACCOUNT, adapter.getItem(position));
+ startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
+ }
+ });
+ popup.setModal(true);
+ popup.show();
+ }
+
@Override
public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
boolean globalSearch) {
diff --git a/src/com/android/contacts/util/AccountsListAdapter.java b/src/com/android/contacts/util/AccountsListAdapter.java
new file mode 100644
index 0000000..09189bb
--- /dev/null
+++ b/src/com/android/contacts/util/AccountsListAdapter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util;
+
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypes;
+import com.android.contacts.model.BaseAccountType;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * List-Adapter for Account selection
+ */
+public final class AccountsListAdapter extends BaseAdapter {
+ private final LayoutInflater mInflater;
+ private final List<Account> mAccounts;
+ private final AccountTypes mSources;
+ private final Context mContext;
+
+ public AccountsListAdapter(Context context, boolean writableOnly) {
+ mContext = context;
+ mSources = AccountTypes.getInstance(context);
+ mAccounts = mSources.getAccounts(writableOnly);
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View resultView = convertView != null ? convertView
+ : mInflater.inflate(R.layout.account_selector_list_item, parent, false);
+
+ final TextView text1 = (TextView)resultView.findViewById(android.R.id.text1);
+ final TextView text2 = (TextView)resultView.findViewById(android.R.id.text2);
+ final ImageView icon = (ImageView)resultView.findViewById(android.R.id.icon);
+
+ final Account account = mAccounts.get(position);
+ final BaseAccountType source = mSources.getInflatedSource(account.type,
+ BaseAccountType.LEVEL_SUMMARY);
+
+ text1.setText(account.name);
+ text2.setText(source.getDisplayLabel(mContext));
+ icon.setImageDrawable(source.getDisplayIcon(mContext));
+
+ return resultView;
+ }
+
+ @Override
+ public int getCount() {
+ return mAccounts.size();
+ }
+
+ @Override
+ public Account getItem(int position) {
+ return mAccounts.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+}
+
diff --git a/src/com/android/contacts/views/editor/ContactEditorFragment.java b/src/com/android/contacts/views/editor/ContactEditorFragment.java
index 64980a8..199c515 100644
--- a/src/com/android/contacts/views/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/views/editor/ContactEditorFragment.java
@@ -66,6 +66,7 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.RawContacts;
import android.provider.MediaStore;
import android.text.TextUtils;
@@ -266,7 +267,16 @@
} else if (Intent.ACTION_INSERT.equals(mAction)) {
if (mListener != null) mListener.setTitleTo(R.string.editContact_title_insert);
- doAddAction(true);
+ final Account account = mIntentExtras == null ? null :
+ (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT);
+
+ if (account != null) {
+ // Account specified in Intent
+ createContact(account, true);
+ } else {
+ // No Account specified. Let the user choose
+ doAddAction(true);
+ }
} else throw new IllegalArgumentException("Unknown Action String " + mAction +
". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
}
diff --git a/src/com/android/contacts/views/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/views/editor/SelectAccountDialogFragment.java
index 496571d..32e88d8 100644
--- a/src/com/android/contacts/views/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/views/editor/SelectAccountDialogFragment.java
@@ -17,8 +17,7 @@
package com.android.contacts.views.editor;
import com.android.contacts.R;
-import com.android.contacts.model.BaseAccountType;
-import com.android.contacts.model.AccountTypes;
+import com.android.contacts.util.AccountsListAdapter;
import android.accounts.Account;
import android.app.AlertDialog;
@@ -27,13 +26,6 @@
import android.app.Fragment;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import java.util.ArrayList;
/**
* Shows a dialog asking the user which account to chose.
@@ -71,38 +63,10 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AccountTypes sources = AccountTypes.getInstance(getActivity());
- final ArrayList<Account> accounts =
- AccountTypes.getInstance(getActivity()).getAccounts(true);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- final LayoutInflater inflater = LayoutInflater.from(builder.getContext());
- final ArrayAdapter<Account> accountAdapter = new ArrayAdapter<Account>(builder.getContext(),
- android.R.layout.simple_list_item_2, accounts) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final View resultView;
- if (convertView == null) {
- resultView = inflater.inflate(android.R.layout.simple_list_item_2,
- parent, false);
- } else {
- resultView = convertView;
- }
-
- // TODO: show icon along with title
- final TextView text1 = (TextView)resultView.findViewById(android.R.id.text1);
- final TextView text2 = (TextView)resultView.findViewById(android.R.id.text2);
-
- final Account account = this.getItem(position);
- final BaseAccountType source = sources.getInflatedSource(account.type,
- BaseAccountType.LEVEL_SUMMARY);
-
- text1.setText(account.name);
- text2.setText(source.getDisplayLabel(getContext()));
-
- return resultView;
- }
- };
+ final AccountsListAdapter accountAdapter = new AccountsListAdapter(builder.getContext(),
+ true);
final DialogInterface.OnClickListener clickListener =
new DialogInterface.OnClickListener() {
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 0c5ee70..54f7939 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -18,11 +18,13 @@
package="com.android.contacts.tests">
<uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<application>
<uses-library android:name="android.test.runner" />
<meta-data android:name="com.android.contacts.iconset" android:resource="@xml/iconset" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<activity android:name=".allintents.AllIntentsActivity"
android:label="@string/contactsIntents"
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index 25e10b0..419ae98 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -71,6 +71,8 @@
<item>EDIT (legacy style uri)</item>
<item>EDIT (create new contact)</item>
<item>EDIT (create new contact with data)</item>
+ <item>EDIT (create new contact for account)</item>
+ <item>EDIT (create new contact for account with data)</item>
<item>EDIT (create new raw contact)</item>
<item>EDIT (create new legacy)</item>
diff --git a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
index 5283f5f..bf75ed1 100644
--- a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
@@ -21,6 +21,7 @@
import com.android.contacts.tests.R;
import com.google.android.collect.Lists;
+import android.accounts.Account;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.ComponentName;
@@ -53,7 +54,8 @@
* Useful for manual and scripted tests.
*/
@SuppressWarnings("deprecation")
-public class AllIntentsActivity extends ListActivity {
+public class AllIntentsActivity extends ListActivity
+ implements SelectAccountDialogFragment.Listener {
private static final String ANDROID_CONTACTS_PACKAGE = "com.android.contacts";
@@ -114,14 +116,16 @@
private static final int EDIT_LEGACY = 46;
private static final int EDIT_NEW_CONTACT = 47;
private static final int EDIT_NEW_CONTACT_WITH_DATA = 48;
- private static final int EDIT_NEW_RAW_CONTACT = 49;
- private static final int EDIT_NEW_LEGACY = 50;
+ private static final int EDIT_NEW_CONTACT_FOR_ACCOUNT = 49;
+ private static final int EDIT_NEW_CONTACT_FOR_ACCOUNT_WITH_DATA = 50;
+ private static final int EDIT_NEW_RAW_CONTACT = 51;
+ private static final int EDIT_NEW_LEGACY = 52;
- private static final int VIEW_CONTACT = 51;
- private static final int VIEW_CONTACT_LOOKUP = 52;
- private static final int VIEW_CONTACT_LOOKUP_ID = 53;
- private static final int VIEW_RAW_CONTACT = 54;
- private static final int VIEW_LEGACY = 55;
+ private static final int VIEW_CONTACT = 53;
+ private static final int VIEW_CONTACT_LOOKUP = 54;
+ private static final int VIEW_CONTACT_LOOKUP_ID = 55;
+ private static final int VIEW_RAW_CONTACT = 56;
+ private static final int VIEW_LEGACY = 57;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -444,6 +448,13 @@
startActivity(intent);
break;
}
+ case EDIT_NEW_CONTACT_FOR_ACCOUNT:
+ case EDIT_NEW_CONTACT_FOR_ACCOUNT_WITH_DATA: {
+ final SelectAccountDialogFragment dialog = new SelectAccountDialogFragment();
+ dialog.setArguments(SelectAccountDialogFragment.createBundle(position));
+ dialog.show(getFragmentManager(), SelectAccountDialogFragment.TAG);
+ break;
+ }
case EDIT_NEW_RAW_CONTACT: {
startActivity(new Intent(Intent.ACTION_INSERT, RawContacts.CONTENT_URI));
break;
@@ -576,4 +587,35 @@
return -1;
}
+
+ @Override
+ public void onAccountChosen(Account account, int tag) {
+ switch (tag) {
+ case EDIT_NEW_CONTACT_FOR_ACCOUNT: {
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ intent.putExtra(Insert.ACCOUNT, account);
+ startActivity(intent);
+ break;
+ }
+ case EDIT_NEW_CONTACT_FOR_ACCOUNT_WITH_DATA: {
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+
+ intent.putExtra(Insert.ACCOUNT, account);
+ ContentValues row1 = new ContentValues();
+ row1.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
+ row1.put(Organization.COMPANY, "Android");
+
+ ContentValues row2 = new ContentValues();
+ row2.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ row2.put(Email.TYPE, Email.TYPE_CUSTOM);
+ row2.put(Email.LABEL, "Green Bot");
+ row2.put(Email.ADDRESS, "android@android.com");
+
+ intent.putParcelableArrayListExtra(Insert.DATA, Lists.newArrayList(row1, row2));
+
+ startActivity(intent);
+ break;
+ }
+ }
+ }
}
diff --git a/tests/src/com/android/contacts/tests/allintents/SelectAccountDialogFragment.java b/tests/src/com/android/contacts/tests/allintents/SelectAccountDialogFragment.java
new file mode 100644
index 0000000..e074a0b
--- /dev/null
+++ b/tests/src/com/android/contacts/tests/allintents/SelectAccountDialogFragment.java
@@ -0,0 +1,97 @@
+/*
+ * 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.tests.allintents;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+/**
+ * Shows a dialog asking the user which account to chose.
+ * The result is passed back to the owning Activity
+ * Does not perform any action by itself.
+ */
+public class SelectAccountDialogFragment extends DialogFragment {
+ public static final String TAG = "SelectAccountDialogFragment";
+
+ private static final String EXTRA_TAG = "tag";
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle parameters = getArguments();
+
+ final Account[] accounts = AccountManager.get(getActivity()).getAccounts();
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ final LayoutInflater inflater = LayoutInflater.from(builder.getContext());
+
+ final ArrayAdapter<Account> accountAdapter = new ArrayAdapter<Account>(builder.getContext(),
+ android.R.layout.simple_list_item_2, accounts) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View resultView = convertView == null
+ ? inflater.inflate(android.R.layout.simple_list_item_2, parent, false)
+ : convertView;
+
+ final TextView text1 = (TextView)resultView.findViewById(android.R.id.text1);
+ final TextView text2 = (TextView)resultView.findViewById(android.R.id.text2);
+
+ final Account account = getItem(position);
+
+ text1.setText("Name: " + account.name);
+ text2.setText("Type: " + account.type);
+
+ return resultView;
+ }
+ };
+
+ final DialogInterface.OnClickListener clickListener =
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+
+ ((Listener) getActivity()).onAccountChosen(accountAdapter.getItem(which),
+ parameters.getInt(EXTRA_TAG));
+ }
+ };
+
+ builder.setTitle("Choose account to send to editor");
+ builder.setSingleChoiceItems(accountAdapter, 0, clickListener);
+ final AlertDialog result = builder.create();
+ return result;
+ }
+
+ public static Bundle createBundle(int tag) {
+ final Bundle result = new Bundle();
+ result.putInt(EXTRA_TAG, tag);
+ return result;
+ }
+
+ public interface Listener {
+ void onAccountChosen(Account account, int tag);
+ }
+}