1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts.editor; 18 19 import com.android.contacts.ContactsUtils; 20 import com.android.contacts.R; 21 import com.android.contacts.model.AccountType; 22 import com.android.contacts.model.AccountWithDataSet; 23 import com.android.contacts.model.DataKind; 24 import com.android.contacts.model.EntityDelta; 25 import com.android.contacts.model.EntityDelta.ValuesDelta; 26 import com.android.contacts.model.EntityModifier; 27 28 import android.content.ContentUris; 29 import android.content.Context; 30 import android.content.res.Resources; 31 import android.net.Uri; 32 import android.provider.ContactsContract.CommonDataKinds.Email; 33 import android.provider.ContactsContract.CommonDataKinds.Phone; 34 import android.provider.ContactsContract.CommonDataKinds.Photo; 35 import android.provider.ContactsContract.CommonDataKinds.StructuredName; 36 import android.provider.ContactsContract.RawContacts; 37 import android.telephony.PhoneNumberUtils; 38 import android.text.TextUtils; 39 import android.util.AttributeSet; 40 import android.view.LayoutInflater; 41 import android.view.View; 42 import android.view.View.OnClickListener; 43 import android.view.ViewGroup; 44 import android.widget.Button; 45 import android.widget.ImageView; 46 import android.widget.TextView; 47 import android.widget.Toast; 48 49 import java.util.ArrayList; 50 51 /** 52 * Custom view that displays external contacts in the edit screen. 53 */ 54 public class RawContactReadOnlyEditorView extends BaseRawContactEditorView 55 implements OnClickListener { 56 private LayoutInflater mInflater; 57 58 private TextView mName; 59 private Button mEditExternallyButton; 60 private ViewGroup mGeneral; 61 62 private View mAccountContainer; 63 private ImageView mAccountIcon; 64 private TextView mAccountTypeTextView; 65 private TextView mAccountNameTextView; 66 67 private String mAccountName; 68 private String mAccountType; 69 private String mDataSet; 70 private long mRawContactId = -1; 71 72 private Listener mListener; 73 74 public interface Listener { 75 void onExternalEditorRequest(AccountWithDataSet account, Uri uri); 76 } 77 78 public RawContactReadOnlyEditorView(Context context) { 79 super(context); 80 } 81 82 public RawContactReadOnlyEditorView(Context context, AttributeSet attrs) { 83 super(context, attrs); 84 } 85 86 public void setListener(Listener listener) { 87 mListener = listener; 88 } 89 90 /** {@inheritDoc} */ 91 @Override 92 protected void onFinishInflate() { 93 super.onFinishInflate(); 94 95 mInflater = (LayoutInflater)getContext().getSystemService( 96 Context.LAYOUT_INFLATER_SERVICE); 97 98 mName = (TextView) findViewById(R.id.read_only_name); 99 mEditExternallyButton = (Button) findViewById(R.id.button_edit_externally); 100 mEditExternallyButton.setOnClickListener(this); 101 mGeneral = (ViewGroup)findViewById(R.id.sect_general); 102 103 mAccountContainer = findViewById(R.id.account_container); 104 mAccountIcon = (ImageView) findViewById(R.id.account_icon); 105 mAccountTypeTextView = (TextView) findViewById(R.id.account_type); 106 mAccountNameTextView = (TextView) findViewById(R.id.account_name); 107 } 108 109 /** 110 * Set the internal state for this view, given a current 111 * {@link EntityDelta} state and the {@link AccountType} that 112 * apply to that state. 113 */ 114 @Override 115 public void setState(EntityDelta state, AccountType type, ViewIdGenerator vig, 116 boolean isProfile) { 117 // Remove any existing sections 118 mGeneral.removeAllViews(); 119 120 // Bail if invalid state or source 121 if (state == null || type == null) return; 122 123 // Make sure we have StructuredName 124 EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE); 125 126 // Fill in the header info 127 ValuesDelta values = state.getValues(); 128 mAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 129 mAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 130 mDataSet = values.getAsString(RawContacts.DATA_SET); 131 132 if (isProfile) { 133 if (TextUtils.isEmpty(mAccountName)) { 134 mAccountNameTextView.setVisibility(View.GONE); 135 mAccountTypeTextView.setText(R.string.local_profile_title); 136 } else { 137 CharSequence accountType = type.getDisplayLabel(mContext); 138 mAccountTypeTextView.setText(mContext.getString(R.string.external_profile_title, 139 accountType)); 140 mAccountNameTextView.setText(mAccountName); 141 } 142 } else { 143 CharSequence accountType = type.getDisplayLabel(mContext); 144 if (TextUtils.isEmpty(accountType)) { 145 accountType = mContext.getString(R.string.account_phone); 146 } 147 if (!TextUtils.isEmpty(mAccountName)) { 148 mAccountNameTextView.setVisibility(View.VISIBLE); 149 mAccountNameTextView.setText( 150 mContext.getString(R.string.from_account_format, mAccountName)); 151 } else { 152 // Hide this view so the other text view will be centered vertically 153 mAccountNameTextView.setVisibility(View.GONE); 154 } 155 mAccountTypeTextView.setText(mContext.getString(R.string.account_type_format, 156 accountType)); 157 } 158 mAccountTypeTextView.setTextColor(mContext.getResources().getColor( 159 R.color.secondary_text_color)); 160 161 // TODO: Expose data set in the UI somehow? 162 163 mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext)); 164 165 mRawContactId = values.getAsLong(RawContacts._ID); 166 167 ValuesDelta primary; 168 169 // Photo 170 DataKind kind = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE); 171 if (kind != null) { 172 EntityModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE); 173 boolean hasPhotoEditor = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null; 174 setHasPhotoEditor(hasPhotoEditor); 175 primary = state.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 176 getPhotoEditor().setValues(kind, primary, state, !type.areContactsWritable(), vig); 177 } 178 179 // Name 180 primary = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE); 181 mName.setText(primary != null ? primary.getAsString(StructuredName.DISPLAY_NAME) : 182 mContext.getString(R.string.missing_name)); 183 184 if (type.getEditContactActivityClassName() != null) { 185 mAccountContainer.setBackgroundDrawable(null); 186 mAccountContainer.setEnabled(false); 187 mEditExternallyButton.setVisibility(View.VISIBLE); 188 } else { 189 mAccountContainer.setOnClickListener(new OnClickListener() { 190 @Override 191 public void onClick(View v) { 192 Toast.makeText(mContext, mContext.getString(R.string.contact_read_only), 193 Toast.LENGTH_SHORT).show(); 194 } 195 }); 196 mEditExternallyButton.setVisibility(View.GONE); 197 } 198 199 final Resources res = mContext.getResources(); 200 // Phones 201 ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE); 202 if (phones != null) { 203 for (int i = 0; i < phones.size(); i++) { 204 ValuesDelta phone = phones.get(i); 205 final String phoneNumber = PhoneNumberUtils.formatNumber( 206 phone.getAsString(Phone.NUMBER), 207 phone.getAsString(Phone.NORMALIZED_NUMBER), 208 ContactsUtils.getCurrentCountryIso(getContext())); 209 final CharSequence phoneType; 210 if (phone.containsKey(Phone.TYPE)) { 211 phoneType = Phone.getTypeLabel( 212 res, phone.getAsInteger(Phone.TYPE), phone.getAsString(Phone.LABEL)); 213 } else { 214 phoneType = null; 215 } 216 bindData(mContext.getText(R.string.phoneLabelsGroup), 217 phoneNumber, phoneType, i == 0); 218 } 219 } 220 221 // Emails 222 ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE); 223 if (emails != null) { 224 for (int i = 0; i < emails.size(); i++) { 225 ValuesDelta email = emails.get(i); 226 final String emailAddress = email.getAsString(Email.DATA); 227 final CharSequence emailType; 228 if (email.containsKey(Email.TYPE)) { 229 emailType = Email.getTypeLabel( 230 res, email.getAsInteger(Email.TYPE), email.getAsString(Email.LABEL)); 231 } else { 232 emailType = null; 233 } 234 bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, emailType, 235 i == 0); 236 } 237 } 238 239 // Hide mGeneral if it's empty 240 if (mGeneral.getChildCount() > 0) { 241 mGeneral.setVisibility(View.VISIBLE); 242 } else { 243 mGeneral.setVisibility(View.GONE); 244 } 245 } 246 247 private void bindData( 248 CharSequence titleText, CharSequence data, CharSequence type, boolean isFirstEntry) { 249 final View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false); 250 final View divider = field.findViewById(R.id.divider); 251 if (isFirstEntry) { 252 final TextView titleView = (TextView) field.findViewById(R.id.kind_title); 253 titleView.setText(titleText); 254 divider.setVisibility(View.GONE); 255 } else { 256 View titleContainer = field.findViewById(R.id.kind_title_layout); 257 titleContainer.setVisibility(View.GONE); 258 divider.setVisibility(View.VISIBLE); 259 } 260 final TextView dataView = (TextView) field.findViewById(R.id.data); 261 dataView.setText(data); 262 final TextView typeView = (TextView) field.findViewById(R.id.type); 263 if (!TextUtils.isEmpty(type)) { 264 typeView.setText(type); 265 } else { 266 typeView.setVisibility(View.GONE); 267 } 268 269 mGeneral.addView(field); 270 } 271 272 @Override 273 public long getRawContactId() { 274 return mRawContactId; 275 } 276 277 @Override 278 public void onClick(View v) { 279 if (v.getId() == R.id.button_edit_externally) { 280 if (mListener != null) { 281 mListener.onExternalEditorRequest( 282 new AccountWithDataSet(mAccountName, mAccountType, mDataSet), 283 ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactId)); 284 } 285 } 286 } 287 } 288