Home | History | Annotate | Download | only in editor
      1 /*
      2  * Copyright (C) 2010 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.Context;
     20 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     21 import android.text.TextUtils;
     22 import android.util.AttributeSet;
     23 
     24 import com.android.contacts.model.RawContactDelta;
     25 import com.android.contacts.common.model.ValuesDelta;
     26 import com.android.contacts.common.model.dataitem.DataKind;
     27 import com.android.contacts.model.dataitem.StructuredNameDataItem;
     28 
     29 /**
     30  * A dedicated editor for phonetic name. It is similar to {@link StructuredNameEditorView}.
     31  */
     32 public class PhoneticNameEditorView extends TextFieldsEditorView {
     33 
     34     private static class PhoneticValuesDelta extends ValuesDelta {
     35         private ValuesDelta mValues;
     36         private String mPhoneticName;
     37 
     38         public PhoneticValuesDelta(ValuesDelta values) {
     39             mValues = values;
     40             buildPhoneticName();
     41         }
     42 
     43         @Override
     44         public void put(String key, String value) {
     45             if (key.equals(DataKind.PSEUDO_COLUMN_PHONETIC_NAME)) {
     46                 mPhoneticName = value;
     47                 parsePhoneticName(value);
     48             } else {
     49                 mValues.put(key, value);
     50                 buildPhoneticName();
     51             }
     52         }
     53 
     54         @Override
     55         public String getAsString(String key) {
     56             if (key.equals(DataKind.PSEUDO_COLUMN_PHONETIC_NAME)) {
     57                 return mPhoneticName;
     58             } else {
     59                 return mValues.getAsString(key);
     60             }
     61         }
     62 
     63         private void parsePhoneticName(String value) {
     64             StructuredNameDataItem dataItem = PhoneticNameEditorView.parsePhoneticName(value, null);
     65             mValues.setPhoneticFamilyName(dataItem.getPhoneticFamilyName());
     66             mValues.setPhoneticMiddleName(dataItem.getPhoneticMiddleName());
     67             mValues.setPhoneticGivenName(dataItem.getPhoneticGivenName());
     68         }
     69 
     70         private void buildPhoneticName() {
     71             String family = mValues.getPhoneticFamilyName();
     72             String middle = mValues.getPhoneticMiddleName();
     73             String given = mValues.getPhoneticGivenName();
     74             mPhoneticName = PhoneticNameEditorView.buildPhoneticName(family, middle, given);
     75         }
     76 
     77         @Override
     78         public Long getId() {
     79             return mValues.getId();
     80         }
     81 
     82         @Override
     83         public boolean isVisible() {
     84             return mValues.isVisible();
     85         }
     86     }
     87 
     88     /**
     89      * Parses phonetic name and returns parsed data (family, middle, given) as ContentValues.
     90      * Parsed data should be {@link StructuredName#PHONETIC_FAMILY_NAME},
     91      * {@link StructuredName#PHONETIC_MIDDLE_NAME}, and
     92      * {@link StructuredName#PHONETIC_GIVEN_NAME}.
     93      * If this method cannot parse given phoneticName, null values will be stored.
     94      *
     95      * @param phoneticName Phonetic name to be parsed
     96      * @param values ContentValues to be used for storing data. If null, new instance will be
     97      * created.
     98      * @return ContentValues with parsed data. Those data can be null.
     99      */
    100     public static StructuredNameDataItem parsePhoneticName(String phoneticName,
    101             StructuredNameDataItem item) {
    102         String family = null;
    103         String middle = null;
    104         String given = null;
    105 
    106         if (!TextUtils.isEmpty(phoneticName)) {
    107             String[] strings = phoneticName.split(" ", 3);
    108             switch (strings.length) {
    109                 case 1:
    110                     family = strings[0];
    111                     break;
    112                 case 2:
    113                     family = strings[0];
    114                     given = strings[1];
    115                     break;
    116                 case 3:
    117                     family = strings[0];
    118                     middle = strings[1];
    119                     given = strings[2];
    120                     break;
    121             }
    122         }
    123 
    124         if (item == null) {
    125             item = new StructuredNameDataItem();
    126         }
    127         item.setPhoneticFamilyName(family);
    128         item.setPhoneticMiddleName(middle);
    129         item.setPhoneticGivenName(given);
    130         return item;
    131     }
    132 
    133     /**
    134      * Constructs and returns a phonetic full name from given parts.
    135      */
    136     public static String buildPhoneticName(String family, String middle, String given) {
    137         if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
    138                 || !TextUtils.isEmpty(given)) {
    139             StringBuilder sb = new StringBuilder();
    140             if (!TextUtils.isEmpty(family)) {
    141                 sb.append(family.trim()).append(' ');
    142             }
    143             if (!TextUtils.isEmpty(middle)) {
    144                 sb.append(middle.trim()).append(' ');
    145             }
    146             if (!TextUtils.isEmpty(given)) {
    147                 sb.append(given.trim()).append(' ');
    148             }
    149             sb.setLength(sb.length() - 1);  // Yank the last space
    150             return sb.toString();
    151         } else {
    152             return null;
    153         }
    154     }
    155 
    156     public static boolean isUnstructuredPhoneticNameColumn(String column) {
    157         return DataKind.PSEUDO_COLUMN_PHONETIC_NAME.equals(column);
    158     }
    159 
    160     public PhoneticNameEditorView(Context context) {
    161         super(context);
    162     }
    163 
    164     public PhoneticNameEditorView(Context context, AttributeSet attrs) {
    165         super(context, attrs);
    166     }
    167 
    168     public PhoneticNameEditorView(Context context, AttributeSet attrs, int defStyle) {
    169         super(context, attrs, defStyle);
    170     }
    171 
    172     @Override
    173     public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
    174             ViewIdGenerator vig) {
    175         if (!(entry instanceof PhoneticValuesDelta)) {
    176             entry = new PhoneticValuesDelta(entry);
    177         }
    178         super.setValues(kind, entry, state, readOnly, vig);
    179     }
    180 
    181     @Override
    182     public void onFieldChanged(String column, String value) {
    183         if (!isFieldChanged(column, value)) {
    184             return;
    185         }
    186 
    187         if (hasShortAndLongForms()) {
    188             PhoneticValuesDelta entry = (PhoneticValuesDelta) getEntry();
    189 
    190             // Determine whether the user is modifying the structured or unstructured phonetic
    191             // name field. See a similar approach in {@link StructuredNameEditor#onFieldChanged}.
    192             // This is because on device rotation, a hidden TextView's onRestoreInstanceState() will
    193             // be called and incorrectly restore a null value for the hidden field, which ultimately
    194             // modifies the underlying phonetic name. Hence, ignore onFieldChanged() update requests
    195             // from fields that aren't visible.
    196             boolean isEditingUnstructuredPhoneticName = !areOptionalFieldsVisible();
    197 
    198             if (isEditingUnstructuredPhoneticName == isUnstructuredPhoneticNameColumn(column)) {
    199                 // Call into the superclass to update the field and rebuild the underlying
    200                 // phonetic name.
    201                 super.onFieldChanged(column, value);
    202             }
    203         } else {
    204             // All fields are always visible, so we don't have to worry about blocking updates
    205             // from onRestoreInstanceState() from hidden fields. Always call into the superclass
    206             // to update the field and rebuild the underlying phonetic name.
    207             super.onFieldChanged(column, value);
    208         }
    209     }
    210 
    211     public boolean hasData() {
    212         ValuesDelta entry = getEntry();
    213 
    214         String family = entry.getPhoneticFamilyName();
    215         String middle = entry.getPhoneticMiddleName();
    216         String given = entry.getPhoneticGivenName();
    217 
    218         return !TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
    219                 || !TextUtils.isEmpty(given);
    220     }
    221 }
    222