179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan/*
279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Copyright (C) 2011 The Android Open Source Project
379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan *
479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Licensed under the Apache License, Version 2.0 (the "License");
579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * you may not use this file except in compliance with the License.
679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * You may obtain a copy of the License at
779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan *
879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan *      http://www.apache.org/licenses/LICENSE-2.0
979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan *
1079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * Unless required by applicable law or agreed to in writing, software
1179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * distributed under the License is distributed on an "AS IS" BASIS,
1279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * See the License for the specific language governing permissions and
1479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * limitations under the License.
1579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */
1679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
1779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanpackage com.android.contacts.detail;
1879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
19fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.google.common.collect.Iterables;
20fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwell
21fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.R;
22fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.Contact;
23fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.RawContact;
24fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.dataitem.DataItem;
25fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.model.dataitem.OrganizationDataItem;
26fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.common.preference.ContactsPreferences;
27fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwellimport com.android.contacts.util.MoreMath;
28fc50bdd15a2de6560581b67d3b73688a48ae0b3fBrian Attwell
2979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.content.Context;
3065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager;
3165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.pm.PackageManager.NameNotFoundException;
3265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources;
3365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.content.res.Resources.NotFoundException;
3465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.graphics.drawable.Drawable;
353915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.net.Uri;
3679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.provider.ContactsContract.DisplayNameSources;
37c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter;
383915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport android.text.Html;
39c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics;
4079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.text.TextUtils;
4165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerdaimport android.util.Log;
42c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmannimport android.view.MenuItem;
4379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.view.View;
4479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.ImageView;
456c0470e21d8506fb53915df7463634fd47288343Katherine Kuanimport android.widget.ListView;
4679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.widget.TextView;
4779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
483915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoroimport java.util.List;
493915600d2b0ff499e0129e951dfd39bff46b2f42Dave Santoro
5079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan/**
5179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * This class contains utility methods to bind high-level contact details
5279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan * (meaning name, phonetic name, job, and attribution) from a
53851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu * {@link Contact} data object to appropriate {@link View}s.
5479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan */
55333091ae754ddfc25714c14b9b89534be24379f9Paul Soulospublic class ContactDisplayUtils {
56333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos    private static final String TAG = "ContactDisplayUtils";
57c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell    private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance();
5865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
59f748d59e8a31f8c9d054fd11deb9b70250387dabMakoto Onuki    /**
60599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki     * Returns the display name of the contact, using the current display order setting.
61599700fb0182a17435cc86137b5f8bd39b8581e2Makoto Onuki     * Returns res/string/missing_name if there is no display name.
6279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
63851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static CharSequence getDisplayName(Context context, Contact contactData) {
6479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        ContactsPreferences prefs = new ContactsPreferences(context);
65e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert        final CharSequence displayName = contactData.getDisplayName();
66c9bb2179ab321461f88f54d49e9d41f2f6b19fe3Yorke Lee        if (prefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY) {
67e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert            if (!TextUtils.isEmpty(displayName)) {
68c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell                if (contactData.getDisplayNameSource() == DisplayNameSources.PHONE) {
69c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell                    return sBidiFormatter.unicodeWrap(
70c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell                            displayName.toString(), TextDirectionHeuristics.LTR);
71c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell                }
72e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert                return displayName;
7379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            }
7481281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        } else {
75e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert            final CharSequence altDisplayName = contactData.getAltDisplayName();
76e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert            if (!TextUtils.isEmpty(altDisplayName)) {
77e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert                return altDisplayName;
78e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert            }
7979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
80e09b991d963c8207cb4bc64ff45009dd33523e1bAlon Albert        return context.getResources().getString(R.string.missing_name);
8179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
8279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
8379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
8479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Returns the phonetic name of the contact or null if there isn't one.
8579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
86851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static String getPhoneticName(Context context, Contact contactData) {
8779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        String phoneticName = contactData.getPhoneticName();
8879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        if (!TextUtils.isEmpty(phoneticName)) {
8979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            return phoneticName;
9079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
9179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        return null;
9279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
9379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
9479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
95afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan     * Returns the attribution string for the contact, which may specify the contact directory that
96afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan     * the contact came from. Returns null if there is none applicable.
9779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
98851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static String getAttribution(Context context, Contact contactData) {
99afd283a8a65e0cfd62204c948fa2bce3004db657Katherine Kuan        if (contactData.isDirectoryEntry()) {
10079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            String directoryDisplayName = contactData.getDirectoryDisplayName();
10179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            String directoryType = contactData.getDirectoryType();
1022e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            final String displayName;
1032e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            if (!TextUtils.isEmpty(directoryDisplayName)) {
1042e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                displayName = directoryDisplayName;
1052e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            } else if (!TextUtils.isEmpty(directoryType)) {
1062e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                displayName = directoryType;
1072e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            } else {
1082e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                return null;
1092e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            }
11079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            return context.getString(R.string.contact_directory_description, displayName);
11179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
11279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        return null;
11379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
11479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
11579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
11679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Returns the organization of the contact. If several organizations are given,
11779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * the first one is used. Returns null if not applicable.
11879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
119851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static String getCompany(Context context, Contact contactData) {
12079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        final boolean displayNameIsOrganization = contactData.getDisplayNameSource()
12179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                == DisplayNameSources.ORGANIZATION;
122851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        for (RawContact rawContact : contactData.getRawContacts()) {
123851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu            for (DataItem dataItem : Iterables.filter(
124851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    rawContact.getDataItems(), OrganizationDataItem.class)) {
125851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                OrganizationDataItem organization = (OrganizationDataItem) dataItem;
126851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final String company = organization.getCompany();
127851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final String title = organization.getTitle();
128851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final String combined;
129851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                // We need to show company and title in a combined string. However, if the
130851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                // DisplayName is already the organization, it mirrors company or (if company
131851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                // is empty title). Make sure we don't show what's already shown as DisplayName
132851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                if (TextUtils.isEmpty(company)) {
133851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    combined = displayNameIsOrganization ? null : title;
134851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                } else {
135851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    if (TextUtils.isEmpty(title)) {
136851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                        combined = displayNameIsOrganization ? null : company;
13779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                    } else {
138851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                        if (displayNameIsOrganization) {
139851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                            combined = title;
14079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                        } else {
141851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                            combined = context.getString(
142851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                                    R.string.organization_company_and_title,
143851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                                    company, title);
14479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                        }
14579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                    }
146851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                }
14779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
148851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                if (!TextUtils.isEmpty(combined)) {
149851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    return combined;
15079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan                }
15179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            }
15279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
15379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        return null;
15479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
15579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
15679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
15779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Sets the starred state of this contact.
15879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
159c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann    public static void configureStarredImageView(ImageView starredView, boolean isDirectoryEntry,
160c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            boolean isUserProfile, boolean isStarred) {
16179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        // Check if the starred state should be visible
162c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        if (!isDirectoryEntry && !isUserProfile) {
16379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            starredView.setVisibility(View.VISIBLE);
164c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            final int resId = isStarred
165c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    ? R.drawable.btn_star_on_normal_holo_light
166c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    : R.drawable.btn_star_off_normal_holo_light;
167c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredView.setImageResource(resId);
168c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredView.setTag(isStarred);
169c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredView.setContentDescription(starredView.getResources().getString(
170c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    isStarred ? R.string.menu_removeStar : R.string.menu_addStar));
17179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        } else {
17279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            starredView.setVisibility(View.GONE);
173c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        }
174c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann    }
175c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann
176c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann    /**
177c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann     * Sets the starred state of this contact.
178c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann     */
179c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann    public static void configureStarredMenuItem(MenuItem starredMenuItem, boolean isDirectoryEntry,
180c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            boolean isUserProfile, boolean isStarred) {
181c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        // Check if the starred state should be visible
182c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        if (!isDirectoryEntry && !isUserProfile) {
183c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredMenuItem.setVisible(true);
184c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            final int resId = isStarred
185d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    ? R.drawable.ic_star_24dp
186d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    : R.drawable.ic_star_outline_24dp;
187c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredMenuItem.setIcon(resId);
188c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredMenuItem.setChecked(isStarred);
189c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredMenuItem.setTitle(isStarred ? R.string.menu_removeStar : R.string.menu_addStar);
190c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        } else {
191c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            starredMenuItem.setVisible(false);
19279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
19379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
19479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
19579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
1962eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * Sets the display name of this contact to the given {@link TextView}. If
1972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * there is none, then set the view to gone.
1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
199851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static void setDisplayName(Context context, Contact contactData, TextView textView) {
2002eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (textView == null) {
2012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            return;
2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
2032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        setDataOrHideIfNone(getDisplayName(context, contactData), textView);
2042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
2052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2062eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
2072eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * Sets the company and job title of this contact to the given {@link TextView}. If
2082eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * there is none, then set the view to gone.
2092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
210851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static void setCompanyName(Context context, Contact contactData, TextView textView) {
2112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (textView == null) {
2122eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            return;
2132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
2142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        setDataOrHideIfNone(getCompany(context, contactData), textView);
2152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
2162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
21879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Sets the phonetic name of this contact to the given {@link TextView}. If
21979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * there is none, then set the view to gone.
22079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
221851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static void setPhoneticName(Context context, Contact contactData, TextView textView) {
2222eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (textView == null) {
2232eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            return;
2242eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
22579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        setDataOrHideIfNone(getPhoneticName(context, contactData), textView);
22679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
22779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
22879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
22979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Sets the attribution contact to the given {@link TextView}. If
23079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * there is none, then set the view to gone.
23179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
232851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public static void setAttribution(Context context, Contact contactData, TextView textView) {
2332eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        if (textView == null) {
2342eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            return;
2352eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
23679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        setDataOrHideIfNone(getAttribution(context, contactData), textView);
23779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
23879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
23979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
24079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * Helper function to display the given text in the {@link TextView} or
24179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * hides the {@link TextView} if the text is empty or null.
24279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
24379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    private static void setDataOrHideIfNone(CharSequence textToDisplay, TextView textView) {
24479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        if (!TextUtils.isEmpty(textToDisplay)) {
24579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            textView.setText(textToDisplay);
24679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            textView.setVisibility(View.VISIBLE);
24779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        } else {
24879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            textView.setText(null);
24979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan            textView.setVisibility(View.GONE);
25079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
25179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
25279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
253da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki    private static Html.ImageGetter sImageGetter;
254da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki
255da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki    public static Html.ImageGetter getImageGetter(Context context) {
256da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki        if (sImageGetter == null) {
257da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki            sImageGetter = new DefaultImageGetter(context.getPackageManager());
258da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki        }
259da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki        return sImageGetter;
260da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki    }
261da9cdc10fca76c960b43923d7da3abc627655fefMakoto Onuki
26265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda    /** Fetcher for images from resources to be included in HTML text. */
26365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda    private static class DefaultImageGetter implements Html.ImageGetter {
26465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        /** The scheme used to load resources. */
26565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        private static final String RES_SCHEME = "res";
26665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
26765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        private final PackageManager mPackageManager;
26865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
26965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        public DefaultImageGetter(PackageManager packageManager) {
27065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            mPackageManager = packageManager;
27165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        }
27265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
27365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        @Override
27465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        public Drawable getDrawable(String source) {
27565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            // Returning null means that a default image will be used.
27665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            Uri uri;
27765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            try {
27865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                uri = Uri.parse(source);
27965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            } catch (Throwable e) {
28065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Could not parse image source: " + source);
28165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
28265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
28365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            if (!RES_SCHEME.equals(uri.getScheme())) {
28465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Image source does not correspond to a resource: " + source);
28565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
28665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
28765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            // The URI authority represents the package name.
28865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            String packageName = uri.getAuthority();
28965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
29065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            Resources resources = getResourcesForResourceName(packageName);
29165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            if (resources == null) {
29265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Could not parse image source: " + source);
29365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
29465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
29565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
29665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            List<String> pathSegments = uri.getPathSegments();
29765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            if (pathSegments.size() != 1) {
29865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Could not parse image source: " + source);
29965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
30065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
30165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
30265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            final String name = pathSegments.get(0);
30365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            final int resId = resources.getIdentifier(name, "drawable", packageName);
30465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
30565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            if (resId == 0) {
30665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                // Use the default image icon in this case.
30765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Cannot resolve resource identifier: " + source);
30865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
30965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
31065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
31165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            try {
31265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return getResourceDrawable(resources, resId);
31365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            } catch (NotFoundException e) {
31465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Resource not found: " + source, e);
31565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
31665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
31765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        }
31865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
31965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        /** Returns the drawable associated with the given id. */
32065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        private Drawable getResourceDrawable(Resources resources, int resId)
32165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                throws NotFoundException {
32265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            Drawable drawable = resources.getDrawable(resId);
32365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
32465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            return drawable;
32565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        }
32665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda
32765ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        /** Returns the {@link Resources} of the package of the given resource name. */
32865ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        private Resources getResourcesForResourceName(String packageName) {
32965ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            try {
33065ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return mPackageManager.getResourcesForApplication(packageName);
33165ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            } catch (NameNotFoundException e) {
33265ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                Log.d(TAG, "Could not find package: " + packageName);
33365ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda                return null;
33465ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda            }
33565ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda        }
33665ca8b2082300ec9849082e5718b85fbbf30dd31Flavio Lerda    }
33725594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan
33825594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan    /**
33925594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan     * Sets an alpha value on the view.
34025594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan     */
34125594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan    public static void setAlphaOnViewBackground(View view, float alpha) {
34225594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan        if (view != null) {
34325594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan            // Convert alpha layer to a black background HEX color with an alpha value for better
34425594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan            // performance (i.e. use setBackgroundColor() instead of setAlpha())
345187c8167d77687fbc04237c9ac1e87564b2d5f33Josh Gargus            view.setBackgroundColor((int) (MoreMath.clamp(alpha, 0.0f, 1.0f) * 255) << 24);
34625594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan        }
34725594d6db384d27641b402cddf23d44818e1cd10Katherine Kuan    }
3486c0470e21d8506fb53915df7463634fd47288343Katherine Kuan
3496c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    /**
3506c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * Returns the top coordinate of the first item in the {@link ListView}. If the first item
3516c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * in the {@link ListView} is not visible or there are no children in the list, then return
3526c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the
3536c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * list cannot have a positive offset.
3546c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     */
3556c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    public static int getFirstListItemOffset(ListView listView) {
3566c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        if (listView == null || listView.getChildCount() == 0 ||
3576c0470e21d8506fb53915df7463634fd47288343Katherine Kuan                listView.getFirstVisiblePosition() != 0) {
3586c0470e21d8506fb53915df7463634fd47288343Katherine Kuan            return Integer.MIN_VALUE;
3596c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        }
3606c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        return listView.getChildAt(0).getTop();
3616c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    }
3626c0470e21d8506fb53915df7463634fd47288343Katherine Kuan
3636c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    /**
3646c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * Tries to scroll the first item in the list to the given offset (this can be a no-op if the
3656c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * list is already in the correct position).
3666c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * @param listView that should be scrolled
3676c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     * @param offset which should be <= 0
3686c0470e21d8506fb53915df7463634fd47288343Katherine Kuan     */
3696c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    public static void requestToMoveToOffset(ListView listView, int offset) {
3706c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // We try to offset the list if the first item in the list is showing (which is presumed
3716c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // to have a larger height than the desired offset). If the first item in the list is not
3726c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // visible, then we simply do not scroll the list at all (since it can get complicated to
3736c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // compute how many items in the list will equal the given offset). Potentially
3746c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // some animation elsewhere will make the transition smoother for the user to compensate
3756c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // for this simplification.
3766c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        if (listView == null || listView.getChildCount() == 0 ||
3776c0470e21d8506fb53915df7463634fd47288343Katherine Kuan                listView.getFirstVisiblePosition() != 0 || offset > 0) {
3786c0470e21d8506fb53915df7463634fd47288343Katherine Kuan            return;
3796c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        }
3806c0470e21d8506fb53915df7463634fd47288343Katherine Kuan
3816c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        // As an optimization, check if the first item is already at the given offset.
3826c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        if (listView.getChildAt(0).getTop() == offset) {
3836c0470e21d8506fb53915df7463634fd47288343Katherine Kuan            return;
3846c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        }
3856c0470e21d8506fb53915df7463634fd47288343Katherine Kuan
3866c0470e21d8506fb53915df7463634fd47288343Katherine Kuan        listView.setSelectionFromTop(0, offset);
3876c0470e21d8506fb53915df7463634fd47288343Katherine Kuan    }
38822cb663a251af60bc6beeb1954568c8e6a4c34e9Flavio Lerda}
389