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 View mPhotoStub; 59 private TextView mName; 60 private Button mEditExternallyButton; 61 private ViewGroup mGeneral; 62 63 private View mAccountContainer; 64 private ImageView mAccountIcon; 65 private TextView mAccountTypeTextView; 66 private TextView mAccountNameTextView; 67 68 private String mAccountName; 69 private String mAccountType; 70 private String mDataSet; 71 private long mRawContactId = -1; 72 73 private Listener mListener; 74 75 public interface Listener { 76 void onExternalEditorRequest(AccountWithDataSet account, Uri uri); 77 } 78 79 public RawContactReadOnlyEditorView(Context context) { 80 super(context); 81 } 82 83 public RawContactReadOnlyEditorView(Context context, AttributeSet attrs) { 84 super(context, attrs); 85 } 86 87 public void setListener(Listener listener) { 88 mListener = listener; 89 } 90 91 /** {@inheritDoc} */ 92 @Override 93 protected void onFinishInflate() { 94 super.onFinishInflate(); 95 96 mInflater = (LayoutInflater)getContext().getSystemService( 97 Context.LAYOUT_INFLATER_SERVICE); 98 99 mPhotoStub = findViewById(R.id.stub_photo); 100 101 mName = (TextView) findViewById(R.id.read_only_name); 102 mEditExternallyButton = (Button) findViewById(R.id.button_edit_externally); 103 mEditExternallyButton.setOnClickListener(this); 104 mGeneral = (ViewGroup)findViewById(R.id.sect_general); 105 106 mAccountContainer = findViewById(R.id.account_container); 107 mAccountIcon = (ImageView) findViewById(R.id.account_icon); 108 mAccountTypeTextView = (TextView) findViewById(R.id.account_type); 109 mAccountNameTextView = (TextView) findViewById(R.id.account_name); 110 } 111 112 /** 113 * Set the internal state for this view, given a current 114 * {@link EntityDelta} state and the {@link AccountType} that 115 * apply to that state. 116 */ 117 @Override 118 public void setState(EntityDelta state, AccountType type, ViewIdGenerator vig, 119 boolean isProfile) { 120 // Remove any existing sections 121 mGeneral.removeAllViews(); 122 123 // Bail if invalid state or source 124 if (state == null || type == null) return; 125 126 // Make sure we have StructuredName 127 EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE); 128 129 // Fill in the header info 130 ValuesDelta values = state.getValues(); 131 mAccountName = values.getAsString(RawContacts.ACCOUNT_NAME); 132 mAccountType = values.getAsString(RawContacts.ACCOUNT_TYPE); 133 mDataSet = values.getAsString(RawContacts.DATA_SET); 134 135 if (isProfile) { 136 if (TextUtils.isEmpty(mAccountName)) { 137 mAccountNameTextView.setVisibility(View.GONE); 138 mAccountTypeTextView.setText(R.string.local_profile_title); 139 } else { 140 CharSequence accountType = type.getDisplayLabel(mContext); 141 mAccountTypeTextView.setText(mContext.getString(R.string.external_profile_title, 142 accountType)); 143 mAccountNameTextView.setText(mAccountName); 144 } 145 } else { 146 CharSequence accountType = type.getDisplayLabel(mContext); 147 if (TextUtils.isEmpty(accountType)) { 148 accountType = mContext.getString(R.string.account_phone); 149 } 150 if (!TextUtils.isEmpty(mAccountName)) { 151 mAccountNameTextView.setVisibility(View.VISIBLE); 152 mAccountNameTextView.setText( 153 mContext.getString(R.string.from_account_format, mAccountName)); 154 } else { 155 // Hide this view so the other text view will be centered vertically 156 mAccountNameTextView.setVisibility(View.GONE); 157 } 158 mAccountTypeTextView.setText(mContext.getString(R.string.account_type_format, 159 accountType)); 160 } 161 mAccountTypeTextView.setTextColor(mContext.getResources().getColor( 162 R.color.secondary_text_color)); 163 164 // TODO: Expose data set in the UI somehow? 165 166 mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext)); 167 168 mRawContactId = values.getAsLong(RawContacts._ID); 169 170 ValuesDelta primary; 171 172 // Photo 173 DataKind kind = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE); 174 if (kind != null) { 175 EntityModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE); 176 boolean hasPhotoEditor = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null; 177 setHasPhotoEditor(hasPhotoEditor); 178 primary = state.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 179 getPhotoEditor().setValues(kind, primary, state, !type.areContactsWritable(), vig); 180 if (!hasPhotoEditor || !getPhotoEditor().hasSetPhoto()) { 181 mPhotoStub.setVisibility(View.GONE); 182 } else { 183 mPhotoStub.setVisibility(View.VISIBLE); 184 } 185 } else { 186 mPhotoStub.setVisibility(View.VISIBLE); 187 } 188 189 // Name 190 primary = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE); 191 mName.setText(primary != null ? primary.getAsString(StructuredName.DISPLAY_NAME) : 192 mContext.getString(R.string.missing_name)); 193 194 if (type.getEditContactActivityClassName() != null) { 195 mAccountContainer.setBackgroundDrawable(null); 196 mAccountContainer.setEnabled(false); 197 mEditExternallyButton.setVisibility(View.VISIBLE); 198 } else { 199 mAccountContainer.setOnClickListener(new OnClickListener() { 200 @Override 201 public void onClick(View v) { 202 Toast.makeText(mContext, mContext.getString(R.string.contact_read_only), 203 Toast.LENGTH_SHORT).show(); 204 } 205 }); 206 mEditExternallyButton.setVisibility(View.GONE); 207 } 208 209 final Resources res = mContext.getResources(); 210 // Phones 211 ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE); 212 if (phones != null) { 213 for (int i = 0; i < phones.size(); i++) { 214 ValuesDelta phone = phones.get(i); 215 final String phoneNumber = PhoneNumberUtils.formatNumber( 216 phone.getAsString(Phone.NUMBER), 217 phone.getAsString(Phone.NORMALIZED_NUMBER), 218 ContactsUtils.getCurrentCountryIso(getContext())); 219 final CharSequence phoneType; 220 if (phone.containsKey(Phone.TYPE)) { 221 phoneType = Phone.getTypeLabel( 222 res, phone.getAsInteger(Phone.TYPE), phone.getAsString(Phone.LABEL)); 223 } else { 224 phoneType = null; 225 } 226 bindData(mContext.getText(R.string.phoneLabelsGroup), 227 phoneNumber, phoneType, i == 0); 228 } 229 } 230 231 // Emails 232 ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE); 233 if (emails != null) { 234 for (int i = 0; i < emails.size(); i++) { 235 ValuesDelta email = emails.get(i); 236 final String emailAddress = email.getAsString(Email.DATA); 237 final CharSequence emailType; 238 if (email.containsKey(Email.TYPE)) { 239 emailType = Email.getTypeLabel( 240 res, email.getAsInteger(Email.TYPE), email.getAsString(Email.LABEL)); 241 } else { 242 emailType = null; 243 } 244 bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, emailType, 245 i == 0); 246 } 247 } 248 249 // Hide mGeneral if it's empty 250 if (mGeneral.getChildCount() > 0) { 251 mGeneral.setVisibility(View.VISIBLE); 252 } else { 253 mGeneral.setVisibility(View.GONE); 254 } 255 } 256 257 private void bindData( 258 CharSequence titleText, CharSequence data, CharSequence type, boolean isFirstEntry) { 259 final View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false); 260 final View divider = field.findViewById(R.id.divider); 261 if (isFirstEntry) { 262 final TextView titleView = (TextView) field.findViewById(R.id.kind_title); 263 titleView.setText(titleText); 264 divider.setVisibility(View.GONE); 265 } else { 266 View titleContainer = field.findViewById(R.id.kind_title_layout); 267 titleContainer.setVisibility(View.GONE); 268 divider.setVisibility(View.VISIBLE); 269 } 270 final TextView dataView = (TextView) field.findViewById(R.id.data); 271 dataView.setText(data); 272 final TextView typeView = (TextView) field.findViewById(R.id.type); 273 if (!TextUtils.isEmpty(type)) { 274 typeView.setText(type); 275 } else { 276 typeView.setVisibility(View.GONE); 277 } 278 279 mGeneral.addView(field); 280 } 281 282 @Override 283 public long getRawContactId() { 284 return mRawContactId; 285 } 286 287 @Override 288 public void onClick(View v) { 289 if (v.getId() == R.id.button_edit_externally) { 290 if (mListener != null) { 291 mListener.onExternalEditorRequest( 292 new AccountWithDataSet(mAccountName, mAccountType, mDataSet), 293 ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactId)); 294 } 295 } 296 } 297 } 298