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 android.content.ContentUris; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.net.Uri; 23 import android.provider.ContactsContract.CommonDataKinds.Email; 24 import android.provider.ContactsContract.CommonDataKinds.Phone; 25 import android.provider.ContactsContract.CommonDataKinds.Photo; 26 import android.provider.ContactsContract.CommonDataKinds.StructuredName; 27 import android.provider.ContactsContract.RawContacts; 28 import android.telephony.PhoneNumberUtils; 29 import android.text.TextUtils; 30 import android.util.AttributeSet; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.View.OnClickListener; 34 import android.view.ViewGroup; 35 import android.widget.Button; 36 import android.widget.ImageView; 37 import android.widget.TextView; 38 import android.widget.Toast; 39 40 import com.android.contacts.R; 41 import com.android.contacts.common.GeoUtil; 42 import com.android.contacts.common.model.RawContactModifier; 43 import com.android.contacts.common.model.RawContactDelta; 44 import com.android.contacts.common.model.ValuesDelta; 45 import com.android.contacts.common.model.account.AccountType; 46 import com.android.contacts.common.model.account.AccountWithDataSet; 47 import com.android.contacts.common.model.dataitem.DataKind; 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 RawContactDelta} state and the {@link AccountType} that 112 * apply to that state. 113 */ 114 @Override 115 public void setState(RawContactDelta 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 RawContactModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE); 125 126 // Fill in the header info 127 mAccountName = state.getAccountName(); 128 mAccountType = state.getAccountType(); 129 mDataSet = state.getDataSet(); 130 131 if (isProfile) { 132 if (TextUtils.isEmpty(mAccountName)) { 133 mAccountNameTextView.setVisibility(View.GONE); 134 mAccountTypeTextView.setText(R.string.local_profile_title); 135 } else { 136 CharSequence accountType = type.getDisplayLabel(mContext); 137 mAccountTypeTextView.setText(mContext.getString(R.string.external_profile_title, 138 accountType)); 139 mAccountNameTextView.setText(mAccountName); 140 } 141 } else { 142 CharSequence accountType = type.getDisplayLabel(mContext); 143 if (TextUtils.isEmpty(accountType)) { 144 accountType = mContext.getString(R.string.account_phone); 145 } 146 if (!TextUtils.isEmpty(mAccountName)) { 147 mAccountNameTextView.setVisibility(View.VISIBLE); 148 mAccountNameTextView.setText( 149 mContext.getString(R.string.from_account_format, mAccountName)); 150 } else { 151 // Hide this view so the other text view will be centered vertically 152 mAccountNameTextView.setVisibility(View.GONE); 153 } 154 mAccountTypeTextView.setText(mContext.getString(R.string.account_type_format, 155 accountType)); 156 } 157 mAccountTypeTextView.setTextColor(mContext.getResources().getColor( 158 R.color.secondary_text_color)); 159 160 // TODO: Expose data set in the UI somehow? 161 162 mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext)); 163 164 mRawContactId = state.getRawContactId(); 165 166 ValuesDelta primary; 167 168 // Photo 169 DataKind kind = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE); 170 if (kind != null) { 171 RawContactModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE); 172 boolean hasPhotoEditor = type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null; 173 setHasPhotoEditor(hasPhotoEditor); 174 primary = state.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE); 175 getPhotoEditor().setValues(kind, primary, state, !type.areContactsWritable(), vig); 176 } 177 178 // Name 179 primary = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE); 180 mName.setText(primary != null ? primary.getAsString(StructuredName.DISPLAY_NAME) : 181 mContext.getString(R.string.missing_name)); 182 183 if (type.getEditContactActivityClassName() != null) { 184 mAccountContainer.setBackgroundDrawable(null); 185 mAccountContainer.setEnabled(false); 186 mEditExternallyButton.setVisibility(View.VISIBLE); 187 } else { 188 mAccountContainer.setOnClickListener(new OnClickListener() { 189 @Override 190 public void onClick(View v) { 191 Toast.makeText(mContext, mContext.getString(R.string.contact_read_only), 192 Toast.LENGTH_SHORT).show(); 193 } 194 }); 195 mEditExternallyButton.setVisibility(View.GONE); 196 } 197 198 final Resources res = mContext.getResources(); 199 // Phones 200 ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE); 201 if (phones != null) { 202 for (int i = 0; i < phones.size(); i++) { 203 ValuesDelta phone = phones.get(i); 204 final String phoneNumber = PhoneNumberUtils.formatNumber( 205 phone.getPhoneNumber(), 206 phone.getPhoneNormalizedNumber(), 207 GeoUtil.getCurrentCountryIso(getContext())); 208 final CharSequence phoneType; 209 if (phone.phoneHasType()) { 210 phoneType = Phone.getTypeLabel( 211 res, phone.getPhoneType(), phone.getPhoneLabel()); 212 } else { 213 phoneType = null; 214 } 215 bindData(mContext.getText(R.string.phoneLabelsGroup), phoneNumber, phoneType, 216 i == 0, true); 217 } 218 } 219 220 // Emails 221 ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE); 222 if (emails != null) { 223 for (int i = 0; i < emails.size(); i++) { 224 ValuesDelta email = emails.get(i); 225 final String emailAddress = email.getEmailData(); 226 final CharSequence emailType; 227 if (email.emailHasType()) { 228 emailType = Email.getTypeLabel( 229 res, email.getEmailType(), email.getEmailLabel()); 230 } else { 231 emailType = null; 232 } 233 bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, emailType, 234 i == 0); 235 } 236 } 237 238 // Hide mGeneral if it's empty 239 if (mGeneral.getChildCount() > 0) { 240 mGeneral.setVisibility(View.VISIBLE); 241 } else { 242 mGeneral.setVisibility(View.GONE); 243 } 244 } 245 246 private void bindData(CharSequence titleText, CharSequence data, CharSequence type, 247 boolean isFirstEntry) { 248 bindData(titleText, data, type, isFirstEntry, false); 249 } 250 251 private void bindData(CharSequence titleText, CharSequence data, CharSequence type, 252 boolean isFirstEntry, boolean forceLTR) { 253 final View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false); 254 final View divider = field.findViewById(R.id.divider); 255 if (isFirstEntry) { 256 final TextView titleView = (TextView) field.findViewById(R.id.kind_title); 257 titleView.setText(titleText); 258 divider.setVisibility(View.GONE); 259 } else { 260 View titleContainer = field.findViewById(R.id.kind_title_layout); 261 titleContainer.setVisibility(View.GONE); 262 divider.setVisibility(View.VISIBLE); 263 } 264 final TextView dataView = (TextView) field.findViewById(R.id.data); 265 dataView.setText(data); 266 if (forceLTR) { 267 dataView.setTextDirection(View.TEXT_DIRECTION_LTR); 268 } 269 final TextView typeView = (TextView) field.findViewById(R.id.type); 270 if (!TextUtils.isEmpty(type)) { 271 typeView.setText(type); 272 } else { 273 typeView.setVisibility(View.GONE); 274 } 275 276 mGeneral.addView(field); 277 } 278 279 @Override 280 public long getRawContactId() { 281 return mRawContactId; 282 } 283 284 @Override 285 public void onClick(View v) { 286 if (v.getId() == R.id.button_edit_externally) { 287 if (mListener != null) { 288 mListener.onExternalEditorRequest( 289 new AccountWithDataSet(mAccountName, mAccountType, mDataSet), 290 ContentUris.withAppendedId(RawContacts.CONTENT_URI, mRawContactId)); 291 } 292 } 293 } 294 } 295