Prevent user from creating duplicate labels.
This isn't enforced at the data layer just in the UI's that
allow editting of the group name.
Bug 28718604
Change-Id: I969b0298bd895fdbdd7f8609da05f2b801707c0a
diff --git a/src/com/android/contacts/ContactsDrawerActivity.java b/src/com/android/contacts/ContactsDrawerActivity.java
index e4eef51..bfdc2fb 100644
--- a/src/com/android/contacts/ContactsDrawerActivity.java
+++ b/src/com/android/contacts/ContactsDrawerActivity.java
@@ -88,8 +88,7 @@
AccountFiltersListener,
GroupsListener,
NavigationView.OnNavigationItemSelectedListener,
- SelectAccountDialogFragment.Listener,
- GroupNameEditDialogFragment.Listener {
+ SelectAccountDialogFragment.Listener {
protected static String TAG = "ContactsDrawerActivity";
@@ -650,26 +649,11 @@
@Override
public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
mNewGroupAccount = account;
- GroupNameEditDialogFragment.showInsertDialog(
- getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG);
+ GroupNameEditDialogFragment.newInstanceForCreation(mNewGroupAccount, ACTION_CREATE_GROUP)
+ .show(getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG);
}
@Override
public void onAccountSelectorCancelled() {
}
-
- @Override
- public void onGroupNameEdit(String groupName, boolean isInsert) {
- if (mNewGroupAccount == null) {
- Toast.makeText(this, R.string.groupCreateFailedToast, Toast.LENGTH_SHORT).show();
- return;
- }
- startService(ContactSaveService.createNewGroupIntent(this,
- mNewGroupAccount, groupName, /* rawContactsToAdd */ null, getClass(),
- ACTION_CREATE_GROUP));
- }
-
- @Override
- public void onGroupNameEditCancelled() {
- }
}
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index 093c8b6..68f2f44 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -36,6 +36,7 @@
import com.android.contacts.common.logging.ListEvent;
import com.android.contacts.common.logging.Logger;
import com.android.contacts.common.logging.ScreenEvent.ScreenType;
+import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.group.GroupMembersFragment;
import com.android.contacts.group.GroupMetadata;
@@ -53,8 +54,7 @@
public class GroupMembersActivity extends ContactsDrawerActivity implements
ActionBarAdapter.Listener,
MultiSelectContactsListFragment.OnCheckBoxListActionListener,
- GroupMembersFragment.GroupMembersListener,
- GroupNameEditDialogFragment.Listener {
+ GroupMembersFragment.GroupMembersListener {
private static final String TAG = "GroupMembers";
@@ -382,8 +382,11 @@
return true;
}
case R.id.menu_rename_group: {
- GroupNameEditDialogFragment.showUpdateDialog(
- getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG, mGroupMetadata.groupName);
+ GroupNameEditDialogFragment.newInstanceForUpdate(
+ new AccountWithDataSet(mGroupMetadata.accountName,
+ mGroupMetadata.accountType, mGroupMetadata.dataSet),
+ ACTION_UPDATE_GROUP, mGroupMetadata.groupId, mGroupMetadata.groupName)
+ .show(getFragmentManager(), TAG_GROUP_NAME_EDIT_DIALOG);
return true;
}
case R.id.menu_delete_group: {
@@ -567,23 +570,6 @@
mActionBarAdapter.setSelectionMode(false);
}
- // GroupNameEditDialogFragment.Listener callbacks
-
- @Override
- public void onGroupNameEdit(String groupName, boolean isInsert) {
- if (isInsert) {
- super.onGroupNameEdit(groupName, isInsert);
- return;
- }
- startService(ContactSaveService.createGroupRenameIntent(this,
- mGroupMetadata.groupId, groupName, GroupMembersActivity.class,
- ACTION_UPDATE_GROUP));
- }
-
- @Override
- public void onGroupNameEditCancelled() {
- }
-
// GroupMembersFragment callbacks
@Override
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index d41991c..ba0c2c6 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -38,9 +38,9 @@
import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
+import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.interactions.GroupCreationDialogFragment;
-import com.android.contacts.interactions.GroupCreationDialogFragment.OnGroupCreatedListener;
+import com.android.contacts.group.GroupNameEditDialogFragment;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.RawContactModifier;
@@ -56,6 +56,8 @@
public class GroupMembershipView extends LinearLayout
implements OnClickListener, OnItemClickListener {
+ public static final String TAG_CREATE_GROUP_FRAGMENT = "createGroupDialog";
+
private static final int CREATE_NEW_GROUP_GROUP_ID = 133;
public static final class GroupSelectionItem {
@@ -449,17 +451,23 @@
UiClosables.closeQuietly(mPopup);
mPopup = null;
- GroupCreationDialogFragment.show(
+ final GroupNameEditDialogFragment dialog =
+ GroupNameEditDialogFragment.newInstanceForCreation(
+ new AccountWithDataSet(mAccountName, mAccountType, mDataSet), null);
+
+ // If the device is rotated after the dialog is shown, the listener will become null,
+ // so that the popup from GroupMembershipView will not be shown.
+ dialog.setListener(new GroupNameEditDialogFragment.Listener() {
+ @Override
+ public void onGroupNameEditStarted(String groupName) {
+ mCreatedNewGroup = true;
+ }
+ @Override
+ public void onGroupNameEditCancelled() { }
+ });
+ dialog.show(
((Activity) getContext()).getFragmentManager(),
- mAccountType,
- mAccountName,
- mDataSet,
- new OnGroupCreatedListener() {
- @Override
- public void onGroupCreated() {
- mCreatedNewGroup = true;
- }
- });
+ TAG_CREATE_GROUP_FRAGMENT);
}
}
diff --git a/src/com/android/contacts/group/GroupNameEditDialogFragment.java b/src/com/android/contacts/group/GroupNameEditDialogFragment.java
index 235a878..b2bfd0b 100644
--- a/src/com/android/contacts/group/GroupNameEditDialogFragment.java
+++ b/src/com/android/contacts/group/GroupNameEditDialogFragment.java
@@ -17,11 +17,18 @@
import android.app.Dialog;
import android.app.DialogFragment;
-import android.app.FragmentManager;
+import android.app.LoaderManager;
import android.content.Context;
+import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.Loader;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextUtils;
@@ -33,60 +40,99 @@
import android.widget.EditText;
import android.widget.TextView;
+import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
+import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.google.common.base.Strings;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
/**
* Edits the name of a group.
*/
-public final class GroupNameEditDialogFragment extends DialogFragment {
+public final class GroupNameEditDialogFragment extends DialogFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
- private static final String KEY_IS_INSERT = "isInsert";
private static final String KEY_GROUP_NAME = "groupName";
private static final String ARG_IS_INSERT = "isInsert";
private static final String ARG_GROUP_NAME = "groupName";
+ private static final String ARG_ACCOUNT = "account";
+ private static final String ARG_CALLBACK_ACTION = "callbackAction";
+ private static final String ARG_GROUP_ID = "groupId";
+
+ private static final long NO_GROUP_ID = -1;
+
/** Callbacks for hosts of the {@link GroupNameEditDialogFragment}. */
public interface Listener {
- void onGroupNameEdit(String groupName, boolean isInsert);
+ void onGroupNameEditStarted(String name);
void onGroupNameEditCancelled();
+
+ public static final Listener None = new Listener() {
+ @Override
+ public void onGroupNameEditStarted(String name) { }
+
+ @Override
+ public void onGroupNameEditCancelled() { }
+ };
}
private boolean mIsInsert;
private String mGroupName;
+ private long mGroupId;
+ private Listener mListener;
+ private AccountWithDataSet mAccount;
private EditText mGroupNameEditText;
+ private TextInputLayout mGroupNameTextLayout;
+ private Set<String> mExistingGroups = Collections.emptySet();
- public static void showInsertDialog(FragmentManager fragmentManager, String tag) {
- showDialog(fragmentManager, tag, /* isInsert */ true, /* groupName */ null);
+ public static GroupNameEditDialogFragment newInstanceForCreation(
+ AccountWithDataSet account, String callbackAction) {
+ return newInstance(account, callbackAction, NO_GROUP_ID, null);
}
- public static void showUpdateDialog(FragmentManager fragmentManager,
- String tag, String groupName) {
- showDialog(fragmentManager, tag, /* isInsert */ false, groupName);
+ public static GroupNameEditDialogFragment newInstanceForUpdate(
+ AccountWithDataSet account, String callbackAction, long groupId, String groupName) {
+ return newInstance(account, callbackAction, groupId, groupName);
}
- private static void showDialog(FragmentManager fragmentManager,
- String tag, boolean isInsert, String groupName) {
+ private static GroupNameEditDialogFragment newInstance(
+ AccountWithDataSet account, String callbackAction, long groupId, String groupName) {
+ if (account == null || account.name == null || account.type == null) {
+ throw new IllegalArgumentException("Invalid account");
+ }
+ final boolean isInsert = groupId == NO_GROUP_ID;
final Bundle args = new Bundle();
args.putBoolean(ARG_IS_INSERT, isInsert);
+ args.putLong(ARG_GROUP_ID, groupId);
args.putString(ARG_GROUP_NAME, groupName);
+ args.putParcelable(ARG_ACCOUNT, account);
+ args.putString(ARG_CALLBACK_ACTION, callbackAction);
final GroupNameEditDialogFragment dialog = new GroupNameEditDialogFragment();
dialog.setArguments(args);
- dialog.show(fragmentManager, tag);
+ return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setStyle(STYLE_NORMAL, R.style.ContactsAlertDialogThemeAppCompat);
+ final Bundle args = getArguments();
if (savedInstanceState == null) {
- final Bundle args = getArguments();
- mIsInsert = args.getBoolean(KEY_IS_INSERT);
mGroupName = args.getString(KEY_GROUP_NAME);
} else {
- mIsInsert = savedInstanceState.getBoolean(ARG_IS_INSERT);
mGroupName = savedInstanceState.getString(ARG_GROUP_NAME);
}
+ mGroupId = args.getLong(ARG_GROUP_ID, NO_GROUP_ID);
+ mIsInsert = args.getBoolean(ARG_IS_INSERT, true);
+ mAccount = getArguments().getParcelable(ARG_ACCOUNT);
+
+ // There is only one loader so the id arg doesn't matter.
+ getLoaderManager().initLoader(0, null, this);
}
@Override
@@ -96,7 +142,7 @@
title.setText(mIsInsert
? R.string.group_name_dialog_insert_title
: R.string.group_name_dialog_update_title);
- final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), getTheme())
.setCustomTitle(title)
.setView(R.layout.group_name_edit_dialog)
.setNegativeButton(android.R.string.cancel, new OnClickListener() {
@@ -107,12 +153,9 @@
dismiss();
}
})
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- getListener().onGroupNameEdit(getGroupName(), mIsInsert);
- }
- });
+ // The Positive button listener is defined below in the OnShowListener to
+ // allow for input validation
+ .setPositiveButton(android.R.string.ok, null);
// Disable the create button when the name is empty
final AlertDialog alertDialog = builder.create();
@@ -122,6 +165,8 @@
@Override
public void onShow(DialogInterface dialog) {
mGroupNameEditText = (EditText) alertDialog.findViewById(android.R.id.text1);
+ mGroupNameTextLayout =
+ (TextInputLayout) alertDialog.findViewById(R.id.text_input_layout);
if (!TextUtils.isEmpty(mGroupName)) {
mGroupNameEditText.setText(mGroupName);
// Guard against already created group names that are longer than the max
@@ -134,6 +179,14 @@
final Button createButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
createButton.setEnabled(!TextUtils.isEmpty(getGroupName()));
+
+ // Override the click listener to prevent dismissal if creating a duplicate group.
+ createButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ maybePersistCurrentGroupName(v);
+ }
+ });
mGroupNameEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -145,6 +198,7 @@
@Override
public void afterTextChanged(Editable s) {
+ mGroupNameTextLayout.setError(null);
createButton.setEnabled(!TextUtils.isEmpty(s));
}
});
@@ -154,6 +208,56 @@
return alertDialog;
}
+ /**
+ * Sets the listener for the rename
+ *
+ * Setting a listener on a fragment is error prone since it will be lost if the fragment
+ * is recreated. This exists because it is used from a view class (GroupMembersView) which
+ * needs to modify it's state when this fragment updates the name.
+ *
+ * @param listener the listener. can be null
+ */
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ private boolean hasNameChanged() {
+ final String name = Strings.nullToEmpty(getGroupName());
+ final String originalName = getArguments().getString(ARG_GROUP_NAME);
+ return (mIsInsert && !name.isEmpty()) || !name.equals(originalName);
+ }
+
+ private void maybePersistCurrentGroupName(View button) {
+ if (!hasNameChanged()) {
+ dismiss();
+ return;
+ }
+ final String name = getGroupName();
+ // Note we don't check if the loader finished populating mExistingGroups. It's not the
+ // end of the world if the user ends up with a duplicate group and in practice it should
+ // never really happen (the query should complete much sooner than the user can edit the
+ // label)
+ if (mExistingGroups.contains(name)) {
+ mGroupNameTextLayout.setError(
+ getString(R.string.groupExistsErrorMessage));
+ button.setEnabled(false);
+ return;
+ }
+ final String callbackAction = getArguments().getString(ARG_CALLBACK_ACTION);
+ final Intent serviceIntent;
+ if (mIsInsert) {
+ serviceIntent = ContactSaveService.createNewGroupIntent(getActivity(),
+ new AccountWithDataSet(mAccount.name, mAccount.type, mAccount.dataSet),
+ name, null, getActivity().getClass(), callbackAction);
+ } else {
+ serviceIntent = ContactSaveService.createGroupRenameIntent(getActivity(), mGroupId,
+ name, getActivity().getClass(), callbackAction);
+ }
+ ContactSaveService.startService(getActivity(), serviceIntent);
+ getListener().onGroupNameEditStarted(name);
+ dismiss();
+ }
+
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
@@ -163,10 +267,61 @@
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean(KEY_IS_INSERT, mIsInsert);
outState.putString(KEY_GROUP_NAME, getGroupName());
}
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ // Only a single loader so id is ignored.
+ return new CursorLoader(getActivity(), GroupNameQuery.URI,
+ GroupNameQuery.PROJECTION, GroupNameQuery.getSelection(mAccount),
+ GroupNameQuery.getSelectionArgs(mAccount), null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mExistingGroups = new HashSet<>();
+ while (data.moveToNext()) {
+ mExistingGroups.add(data.getString(GroupNameQuery.TITLE));
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ }
+
+ /**
+ * Defines the structure of the query performed by the CursorLoader created by
+ * GroupNameEditDialogFragment
+ */
+ private static class GroupNameQuery {
+
+ public static final int TITLE = 0;
+ public static final Uri URI = ContactsContract.Groups.CONTENT_URI;
+ public static final String[] PROJECTION = new String[] { ContactsContract.Groups.TITLE };
+
+ public static String getSelection(AccountWithDataSet account) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(ContactsContract.Groups.ACCOUNT_NAME).append("=? AND ")
+ .append(ContactsContract.Groups.ACCOUNT_TYPE).append("=?");
+ if (account.dataSet != null) {
+ builder.append(" AND ").append(ContactsContract.Groups.DATA_SET).append("=?");
+ }
+ return builder.toString();
+ }
+
+ public static String[] getSelectionArgs(AccountWithDataSet account) {
+ final int len = account.dataSet == null ? 2 : 3;
+ final String[] args = new String[len];
+ args[0] = account.name;
+ args[1] = account.type;
+ if (account.dataSet != null) {
+ args[2] = account.dataSet;
+ }
+ return args;
+ }
+ }
+
private void showInputMethod(View view) {
final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE);
@@ -184,11 +339,13 @@
}
private Listener getListener() {
- if (!(getActivity() instanceof Listener)) {
- throw new ClassCastException(getActivity() + " must implement " +
- Listener.class.getName());
+ if (mListener != null) {
+ return mListener;
+ } else if (getActivity() instanceof Listener) {
+ return (Listener) getActivity();
+ } else {
+ return Listener.None;
}
- return (Listener) getActivity();
}
private String getGroupName() {
diff --git a/src/com/android/contacts/group/GroupsFragment.java b/src/com/android/contacts/group/GroupsFragment.java
index be1b44a..508c184 100644
--- a/src/com/android/contacts/group/GroupsFragment.java
+++ b/src/com/android/contacts/group/GroupsFragment.java
@@ -18,7 +18,6 @@
import android.app.Fragment;
import android.app.LoaderManager;
-import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
diff --git a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java b/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
deleted file mode 100644
index e998688..0000000
--- a/src/com/android/contacts/interactions/GroupCreationDialogFragment.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.interactions;
-
-import android.app.Activity;
-import android.app.FragmentManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.widget.EditText;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactEditorBaseActivity;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-
-/**
- * A dialog for creating a new group.
- */
-public class GroupCreationDialogFragment extends GroupNameDialogFragment {
- private static final String ARG_ACCOUNT_TYPE = "accountType";
- private static final String ARG_ACCOUNT_NAME = "accountName";
- private static final String ARG_DATA_SET = "dataSet";
-
- public static final String FRAGMENT_TAG = "createGroupDialog";
-
- private final OnGroupCreatedListener mListener;
-
- public interface OnGroupCreatedListener {
- public void onGroupCreated();
- }
-
- public static void show(
- FragmentManager fragmentManager, String accountType, String accountName,
- String dataSet, OnGroupCreatedListener listener) {
- GroupCreationDialogFragment dialog = new GroupCreationDialogFragment(listener);
- Bundle args = new Bundle();
- args.putString(ARG_ACCOUNT_TYPE, accountType);
- args.putString(ARG_ACCOUNT_NAME, accountName);
- args.putString(ARG_DATA_SET, dataSet);
- dialog.setArguments(args);
- dialog.show(fragmentManager, FRAGMENT_TAG);
- }
-
- public GroupCreationDialogFragment() {
- super();
- mListener = null;
- }
-
- private GroupCreationDialogFragment(OnGroupCreatedListener listener) {
- super();
- mListener = listener;
- }
-
- public OnGroupCreatedListener getOnGroupCreatedListener() {
- return mListener;
- }
-
- @Override
- protected void initializeGroupLabelEditText(EditText editText) {
- }
-
- @Override
- protected int getTitleResourceId() {
- return R.string.create_group_dialog_title;
- }
-
- @Override
- protected void onCompleted(String groupLabel) {
- Bundle arguments = getArguments();
- String accountType = arguments.getString(ARG_ACCOUNT_TYPE);
- String accountName = arguments.getString(ARG_ACCOUNT_NAME);
- String dataSet = arguments.getString(ARG_DATA_SET);
-
- // Indicate to the listener that a new group will be created.
- // If the device is rotated, mListener will become null, so that the
- // popup from GroupMembershipView will not be shown.
- if (mListener != null) {
- mListener.onGroupCreated();
- }
-
- Activity activity = getActivity();
- activity.startService(ContactSaveService.createNewGroupIntent(activity,
- new AccountWithDataSet(accountName, accountType, dataSet), groupLabel,
- null /* no new members to add */,
- activity.getClass(), ContactEditorBaseActivity.ACTION_EDIT));
- }
-}
diff --git a/src/com/android/contacts/interactions/GroupNameDialogFragment.java b/src/com/android/contacts/interactions/GroupNameDialogFragment.java
deleted file mode 100644
index 5efccfc..0000000
--- a/src/com/android/contacts/interactions/GroupNameDialogFragment.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.interactions;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnShowListener;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-
-import com.android.contacts.R;
-
-/**
- * A common superclass for creating and renaming groups.
- */
-// TODO: consolidate it with GroupNameEditDialogFragment
-public abstract class GroupNameDialogFragment extends DialogFragment {
- protected abstract int getTitleResourceId();
- protected abstract void initializeGroupLabelEditText(EditText editText);
- protected abstract void onCompleted(String groupLabel);
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- final LayoutInflater layoutInflater = LayoutInflater.from(builder.getContext());
- final View view = layoutInflater.inflate(R.layout.group_name_dialog, null);
- final EditText editText = (EditText) view.findViewById(R.id.group_label);
- final int maxLength = getResources().getInteger(R.integer.group_name_max_length);
- editText.setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxLength) });
- editText.setInputType(InputType.TYPE_CLASS_TEXT);
- initializeGroupLabelEditText(editText);
-
- builder.setTitle(getTitleResourceId());
- builder.setView(view);
- editText.requestFocus();
- builder.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int whichButton) {
- onCompleted(editText.getText().toString().trim());
- }
- }
- );
-
- builder.setNegativeButton(android.R.string.cancel, null);
- final AlertDialog dialog = builder.create();
-
- dialog.setOnShowListener(new OnShowListener() {
- @Override
- public void onShow(DialogInterface dialogInterface) {
- updateOkButtonState(dialog, editText);
- }
- });
- editText.addTextChangedListener(new TextWatcher() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- updateOkButtonState(dialog, editText);
- }
- });
- dialog.getWindow().setSoftInputMode(
- WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
- return dialog;
- }
-
- /* package */ void updateOkButtonState(AlertDialog dialog, EditText editText) {
- final Button okButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
- okButton.setEnabled(!TextUtils.isEmpty(editText.getText().toString().trim()));
- }
-}