15e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal/* 25e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * Copyright (C) 2012 Google Inc. 35e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * Licensed to The Android Open Source Project. 46f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 56f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 66f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * you may not use this file except in compliance with the License. 76f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * You may obtain a copy of the License at 86f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 95e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal * http://www.apache.org/licenses/LICENSE-2.0 106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * 116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * Unless required by applicable law or agreed to in writing, software 126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * See the License for the specific language governing permissions and 156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * limitations under the License. 166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira */ 175e5ac748eadbb17eee84b39a424b8b9270ade46cVikram Aggarwal 1830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.browse; 196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 20bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereiraimport android.animation.Animator; 21bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereiraimport android.animation.AnimatorSet; 22866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.animation.ObjectAnimator; 23a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sappersteinimport android.content.BroadcastReceiver; 24304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport android.content.Context; 25a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sappersteinimport android.content.Intent; 26a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sappersteinimport android.content.IntentFilter; 276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.content.res.Resources; 286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Bitmap; 296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.BitmapFactory; 306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Canvas; 311fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedyimport android.graphics.Color; 32b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.Paint; 33479505d71969e26b0785d8e0e1b81108731cf827Mark Weiimport android.graphics.Rect; 346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Typeface; 356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.drawable.Drawable; 36be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sappersteinimport android.graphics.drawable.InsetDrawable; 372cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Caoimport android.support.annotation.Nullable; 384eb909e1ef9656dfc06d2518842357827dcfb068Jin Caoimport android.support.v4.text.BidiFormatter; 39928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieuximport android.support.v4.text.TextUtilsCompat; 40a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sappersteinimport android.support.v4.view.ViewCompat; 416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Layout.Alignment; 426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Spannable; 43b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereiraimport android.text.SpannableString; 446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.SpannableStringBuilder; 456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.StaticLayout; 466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextPaint; 476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils; 486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils.TruncateAt; 496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.format.DateUtils; 50be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sappersteinimport android.text.style.BackgroundColorSpan; 516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.CharacterStyle; 526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.ForegroundColorSpan; 532615aea2ce57f5fa3a9cd2e672282818aee6ce94mindypimport android.text.style.TextAppearanceSpan; 546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.util.SparseArray; 55fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huangimport android.util.TypedValue; 566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.MotionEvent; 576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.View; 58850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.ViewGroup; 59370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangimport android.view.ViewParent; 60866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.view.animation.DecelerateInterpolator; 61850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.widget.TextView; 626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 63732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.R; 64042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huangimport com.android.mail.analytics.Analytics; 655f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieuximport com.android.mail.bitmap.CheckableContactFlipDrawable; 66a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Weiimport com.android.mail.bitmap.ContactDrawable; 67732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.perf.Timer; 683dbfbc210a607382ba9c150d7ae373ca0508267cJin Caoimport com.android.mail.providers.Account; 69732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.providers.Conversation; 70b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.providers.Folder; 714a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huangimport com.android.mail.providers.UIProvider; 72c8a994227b9c686d88ee05840544162711a85712Marc Blankimport com.android.mail.providers.UIProvider.ConversationColumns; 73b4a222726f3f1c78b7146fa5f7d4d45974bcef47Andy Huangimport com.android.mail.providers.UIProvider.ConversationListIcon; 7467aa9e5162a15fb8b46b4113ac627cd20668f095Scott Kennedyimport com.android.mail.providers.UIProvider.FolderType; 75bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.ui.AnimatedAdapter; 76e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereiraimport com.android.mail.ui.ControllableActivity; 77ec0fa48764bede0772e9c711f3e33361b62f3608Jin Caoimport com.android.mail.ui.ConversationCheckedSet; 78a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Weiimport com.android.mail.ui.ConversationSetObserver; 79b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.ui.FolderDisplayer; 806c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport com.android.mail.ui.SwipeableItemView; 81a538984fcc19e7624f2650b119ede39bf1f35846mindypimport com.android.mail.ui.SwipeableListView; 82259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedyimport com.android.mail.utils.FolderUri; 83370f868c834861e7732faaa9bdd07a0fa0105596Andy Huangimport com.android.mail.utils.HardwareLayerEnabler; 842f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwalimport com.android.mail.utils.LogTag; 855390fcabb7baf683fc14bd68d8612913dac70a81mindypimport com.android.mail.utils.LogUtils; 86732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.utils.Utils; 87a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sappersteinimport com.android.mail.utils.ViewUtils; 88304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport com.google.common.annotations.VisibleForTesting; 89732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang 9010ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieuximport java.util.List; 91928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieuximport java.util.Locale; 9288acafa03a87f5c84b959697d13b81df8f11a96emindyp 9379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huangpublic class ConversationItemView extends View 943dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao implements SwipeableItemView, ToggleableItem, ConversationSetObserver, 950e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux BadgeSpan.BadgeSpanDimensions { 96479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Timer. 986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static int sLayoutCount = 0; 99bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook private static Timer sTimer; // Create the sTimer here if you need to do 100bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook // perf analysis. 1016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final int PERF_LAYOUT_ITERATIONS = 50; 1026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_LAYOUT = "CCHV.layout"; 1036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_TEXTS_BITMAPS = "CCHV.txtsbmps"; 1046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_SENDER_SUBJECT = "CCHV.sendersubj"; 10530fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira private static final String PERF_TAG_CALCULATE_FOLDERS = "CCHV.folders"; 1066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static final String PERF_TAG_CALCULATE_COORDINATES = "CCHV.coordinates"; 1072f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwal private static final String LOG_TAG = LogTag.getLogTag(); 1086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 109ff35c4d206132d389cc5b77c488bd1fd41926e4dJames Lemieux private static final Typeface SANS_SERIF_BOLD = Typeface.create("sans-serif", Typeface.BOLD); 110ff35c4d206132d389cc5b77c488bd1fd41926e4dJames Lemieux 111f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux private static final Typeface SANS_SERIF_LIGHT = Typeface.create("sans-serif-light", 112f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux Typeface.NORMAL); 113f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux 114ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private static final int[] CHECKED_STATE = new int[] { android.R.attr.state_checked }; 115ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao 1166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static bitmaps. 1176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap STAR_OFF; 1186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap STAR_ON; 1196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static Bitmap ATTACHMENT; 1204a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang private static Bitmap ONLY_TO_ME; 1214a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang private static Bitmap TO_ME_AND_OTHERS; 1224a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang private static Bitmap IMPORTANT_ONLY_TO_ME; 1234a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang private static Bitmap IMPORTANT_TO_ME_AND_OTHERS; 12417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein private static Bitmap IMPORTANT; 12554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_REPLIED; 12654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_FORWARDED; 12754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira private static Bitmap STATE_REPLIED_AND_FORWARDED; 1288d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira private static Bitmap STATE_CALENDAR_INVITE; 1290532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao private static Drawable FOCUSED_CONVERSATION_HIGHLIGHT; 1306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 131ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static String sSendersSplitToken; 132ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira private static String sElidedPaddingToken; 13324538e893ef2db41a4c1b341f676b64422920304Mindy Pereira 1346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static colors. 1355750406080090ed22bf93036525c2ff30f41b28aJames Lemieux private static int sSendersTextColor; 1361c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux private static int sDateTextColorRead; 1371c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux private static int sDateTextColorUnread; 138ce2c0a15773909bfd09935673c4974b5922eba68Alice Yang private static int sStarTouchSlop; 139ce2c0a15773909bfd09935673c4974b5922eba68Alice Yang private static int sSenderImageTouchSlop; 140067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private static int sShrinkAnimationDuration; 141067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private static int sSlideAnimationDuration; 1421fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy private static int sCabAnimationDuration; 143be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private static int sBadgePaddingExtraWidth; 144be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private static int sBadgeRoundedCornerRadius; 1456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Static paints. 1471fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy private static final TextPaint sPaint = new TextPaint(); 1481fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy private static final TextPaint sFoldersPaint = new TextPaint(); 1491fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy private static final Paint sCheckBackgroundPaint = new Paint(); 150cace3194e9b7b0e2b6554bda2fa8b2f98da04175James Lemieux private static final Paint sDividerPaint = new Paint(); 151cace3194e9b7b0e2b6554bda2fa8b2f98da04175James Lemieux 152cace3194e9b7b0e2b6554bda2fa8b2f98da04175James Lemieux private static int sDividerHeight; 1536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 154a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein private static BroadcastReceiver sConfigurationChangedReceiver; 155a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 1566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Backgrounds for different states. 1576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>(); 1586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Dimensions and coordinates. 1606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mViewWidth = -1; 1610d1ed12c6e70f4204ff28092ed51ce540f9f3f67Vikram Aggarwal /** The view mode at which we calculated mViewWidth previously. */ 1620d1ed12c6e70f4204ff28092ed51ce540f9f3f67Vikram Aggarwal private int mPreviousMode; 163479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 16452b280a82df262f62632bd12bba84b4752f14634Scott Kennedy private int mInfoIconX; 1656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mDateX; 166a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein private int mDateWidth; 1676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mPaperclipX; 168a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein private int mSendersX; 1696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private int mSendersWidth; 1706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 171fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal /** Whether we are on a tablet device or not */ 172fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal private final boolean mTabletDevice; 173f0aebd32d750d6e108c8f9b551b1760682123ebbAndy Huang /** When in conversation mode, true if the list is hidden */ 174f0aebd32d750d6e108c8f9b551b1760682123ebbAndy Huang private final boolean mListCollapsible; 1756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @VisibleForTesting 1770944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira ConversationItemViewCoordinates mCoordinates; 1786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 179fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang private ConversationItemViewCoordinates.Config mConfig; 180fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 1816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private final Context mContext; 1826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1833dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao private ConversationItemViewModel mHeader; 184c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira private boolean mDownEvent; 185ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private boolean mChecked = false; 186ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private ConversationCheckedSet mCheckedConversationSet; 1874584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira private Folder mDisplayedFolder; 1880a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei private boolean mStarEnabled; 189f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira private boolean mSwipeEnabled; 190a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux private boolean mDividerEnabled; 191bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook private AnimatedAdapter mAdapter; 192370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang private float mAnimatedHeightFraction = 1.0f; 1933dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao private final Account mAccount; 194e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira private ControllableActivity mActivity; 19547cb510ea11c8886434575118068fc91eaa25facMark Wei private final TextView mSendersTextView; 196928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux private final TextView mSubjectTextView; 197928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux private final TextView mSnippetTextView; 1984758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang private int mGadgetMode; 199479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 200ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao private static int sFoldersMaxCount; 2016a4c4f62db0ddf6660d889bf1f21e37d25a99363mindyp private static TextAppearanceSpan sSubjectTextUnreadSpan; 2022615aea2ce57f5fa3a9cd2e672282818aee6ce94mindyp private static TextAppearanceSpan sSubjectTextReadSpan; 203be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private static TextAppearanceSpan sBadgeTextSpan; 204be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private static BackgroundColorSpan sBadgeBackgroundSpan; 205d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp private static int sScrollSlop; 2065d07da885ae9d4fdd373995f9c67e2d8f6ebaab9Vikram Aggarwal private static CharacterStyle sActivatedTextSpan; 207479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 2085f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux private final CheckableContactFlipDrawable mSendersImageView; 20979c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 210103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy /** The resource id of the color to use to override the background. */ 211103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy private int mBackgroundOverrideResId = -1; 212103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy /** The bitmap to use, or <code>null</code> for the default */ 213103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy private Bitmap mPhotoBitmap = null; 214c12da4a53eee911765975f0d8afe62f749806b60Jin Cao private Rect mPhotoRect = new Rect(); 215103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy 216d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy /** 217d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy * A listener for clicks on the various areas of a conversation item. 218d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy */ 219d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy public interface ConversationItemAreaClickListener { 220d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy /** Called when the info icon is clicked. */ 221d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy void onInfoIconClicked(); 222d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 223d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy /** Called when the star is clicked. */ 224d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy void onStarClicked(); 225d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 226d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 227d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy /** If set, it will steal all clicks for which the interface has a click method. */ 228d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy private ConversationItemAreaClickListener mConversationItemAreaClickListener = null; 229d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 2306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira static { 2316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setAntiAlias(true); 23230fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira sFoldersPaint.setAntiAlias(true); 2331fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy 2341fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy sCheckBackgroundPaint.setColor(Color.GRAY); 2356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 2366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 237b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira /** 238b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira * Handles displaying folders in a conversation header view. 239b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira */ 240b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira static class ConversationItemFolderDisplayer extends FolderDisplayer { 2414eb909e1ef9656dfc06d2518842357827dcfb068Jin Cao private final BidiFormatter mFormatter; 242b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira private int mFoldersCount; 243b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 2444eb909e1ef9656dfc06d2518842357827dcfb068Jin Cao public ConversationItemFolderDisplayer(Context context, BidiFormatter formatter) { 245c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang super(context); 2464eb909e1ef9656dfc06d2518842357827dcfb068Jin Cao mFormatter = formatter; 247c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang } 248c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang 249b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira @Override 2505edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao protected void initializeDrawableResources() { 2515edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao super.initializeDrawableResources(); 2525edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao final Resources res = mContext.getResources(); 2535edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.overflowGradientPadding = 2545edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao res.getDimensionPixelOffset(R.dimen.folder_tl_gradient_padding); 2555edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderHorizontalPadding = 2565edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao res.getDimensionPixelOffset(R.dimen.folder_tl_cell_content_padding); 2575edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderFontSize = 2585edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao res.getDimensionPixelOffset(R.dimen.folder_tl_font_size); 2595edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao } 2605edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao 2615edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao @Override 262259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy public void loadConversationFolders(Conversation conv, final FolderUri ignoreFolderUri, 26367aa9e5162a15fb8b46b4113ac627cd20668f095Scott Kennedy final int ignoreFolderType) { 26467aa9e5162a15fb8b46b4113ac627cd20668f095Scott Kennedy super.loadConversationFolders(conv, ignoreFolderUri, ignoreFolderType); 265c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang mFoldersCount = mFoldersSortedSet.size(); 266b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 267b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 26869495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp @Override 26969495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp public void reset() { 27069495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp super.reset(); 27169495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp mFoldersCount = 0; 27269495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp } 27369495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp 274b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira public boolean hasVisibleFolders() { 275b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return mFoldersCount > 0; 276b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 277b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 278ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao /** 279ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao * @return how much total space the folders list requires. 280ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao */ 281ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao private int measureFolders(ConversationItemViewCoordinates coordinates) { 2825edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao final int[] measurements = measureFolderDimen( 2835edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFoldersSortedSet, coordinates.folderCellWidth, coordinates.folderLayoutWidth, 2845edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderInBetweenPadding, 2855edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderHorizontalPadding, sFoldersMaxCount, 2865edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao sFoldersPaint); 2875edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao return sumWidth(measurements); 288ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao } 289ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao 290ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao private int sumWidth(int[] arr) { 291ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao int sum = 0; 2925edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao for (int i : arr) { 2935edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao sum += i; 294ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao } 2955edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao return sum + (arr.length - 1) * mFolderDrawableResources.folderInBetweenPadding; 296b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 297b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 2985edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao public void drawFolders(Canvas canvas, ConversationItemViewCoordinates coordinates, 2995edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao boolean isRtl) { 300b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira if (mFoldersCount == 0) { 301b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira return; 302b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 303ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao 3045edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao final int[] measurements = measureFolderDimen( 3055edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFoldersSortedSet, coordinates.folderCellWidth, coordinates.folderLayoutWidth, 3065edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderInBetweenPadding, 3075edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderHorizontalPadding, sFoldersMaxCount, 3085edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao sFoldersPaint); 309ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao 310a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein final int right = coordinates.foldersRight; 311fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int y = coordinates.foldersY; 31295f9e1b167f4945adfa4ca62f4b72a102b621794mindyp 313b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira sFoldersPaint.setTextSize(coordinates.foldersFontSize); 314fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang sFoldersPaint.setTypeface(coordinates.foldersTypeface); 315b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 316b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Initialize space and cell size based on the current mode. 3176fce8bb099fc38a68b96486921e9bf03a5b095d4Jin Cao final Paint.FontMetricsInt fm = sFoldersPaint.getFontMetricsInt(); 318ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao final int foldersCount = measurements.length; 319ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao final int width = sumWidth(measurements); 3206fce8bb099fc38a68b96486921e9bf03a5b095d4Jin Cao final int height = fm.bottom - fm.top; 3216adc0bf59acb0e633d0063f16085c286b8423e1bJin Cao int xStart = (isRtl) ? coordinates.snippetX + width : right - width; 322ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao 323ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao int index = 0; 3245edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao for (Folder folder : mFoldersSortedSet) { 325ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao if (index > foldersCount - 1) { 326fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang break; 327fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 328ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao 3295edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao final int actualStart = isRtl ? xStart - measurements[index] : xStart; 3305edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao drawFolder(canvas, actualStart, y, measurements[index], height, folder, 3315edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources, mFormatter, sFoldersPaint); 332b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 3336adc0bf59acb0e633d0063f16085c286b8423e1bJin Cao // Increment the starting position accordingly for the next item 3345edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao final int usedWidth = measurements[index++] + 3355edf5fd7327691b73dcb57c3cba340fd25576d18Jin Cao mFolderDrawableResources.folderInBetweenPadding; 3366adc0bf59acb0e633d0063f16085c286b8423e1bJin Cao xStart += (isRtl) ? -usedWidth : usedWidth; 337ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao } 338ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao } 3392cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao 3402cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao public @Nullable String getFoldersDesc() { 3412cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao if (mFoldersSortedSet != null && !mFoldersSortedSet.isEmpty()) { 3422cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao final StringBuilder builder = new StringBuilder(); 3432cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao final String comma = mContext.getString(R.string.enumeration_comma); 3442cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao for (Folder f : mFoldersSortedSet) { 3452cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao builder.append(f.name).append(comma); 3462cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao } 3472cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao return builder.toString(); 3482cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao } 3492cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao return null; 3502cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao } 351acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira } 352b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 3533dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao public ConversationItemView(Context context, Account account) { 3546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira super(context); 355479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("CIVC constructor"); 356960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira setClickable(true); 357960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira setLongClickable(true); 3586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mContext = context.getApplicationContext(); 359bcb16b98140a83a4db3c51568d21c839595f73dfVikram Aggarwal final Resources res = mContext.getResources(); 360bcb16b98140a83a4db3c51568d21c839595f73dfVikram Aggarwal mTabletDevice = Utils.useTabletUI(res); 36177db7fda313ed4c001eb05fb6b619f9f2798c635Rohan Shah mListCollapsible = !res.getBoolean(R.bool.is_tablet_landscape); 362c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira mAccount = account; 3636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 364a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein getItemViewResources(mContext); 365a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 366928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final int layoutDir = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()); 367928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux 368a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSendersTextView = new TextView(mContext); 369a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSendersTextView.setIncludeFontPadding(false); 370a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 371a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSubjectTextView = new TextView(mContext); 372a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSubjectTextView.setEllipsize(TextUtils.TruncateAt.END); 373a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSubjectTextView.setIncludeFontPadding(false); 374928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux ViewCompat.setLayoutDirection(mSubjectTextView, layoutDir); 375928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux ViewUtils.setTextAlignment(mSubjectTextView, View.TEXT_ALIGNMENT_VIEW_START); 376a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 377928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView = new TextView(mContext); 378928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.setEllipsize(TextUtils.TruncateAt.END); 379928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.setIncludeFontPadding(false); 380f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux mSnippetTextView.setTypeface(SANS_SERIF_LIGHT); 381f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux mSnippetTextView.setTextColor(getResources().getColor(R.color.snippet_text_color)); 382928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux ViewCompat.setLayoutDirection(mSnippetTextView, layoutDir); 383928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux ViewUtils.setTextAlignment(mSnippetTextView, View.TEXT_ALIGNMENT_VIEW_START); 384a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 385f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein // hack for b/16345519. Root cause is b/17280038. 386f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein if (layoutDir == LAYOUT_DIRECTION_RTL) { 387f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein mSubjectTextView.setMaxLines(1); 388f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein mSnippetTextView.setMaxLines(1); 389f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein } else { 390f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein mSubjectTextView.setSingleLine(); 391f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein mSnippetTextView.setSingleLine(); 392f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein } 393f06f4b7bf661125a822606b626de1ab7dbdb188dAndrew Sapperstein 3945f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux mSendersImageView = new CheckableContactFlipDrawable(res, sCabAnimationDuration); 395a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein mSendersImageView.setCallback(this); 396a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 397a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein Utils.traceEndSection(); 398a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein } 399a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein 400a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein private static synchronized void getItemViewResources(Context context) { 401a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein if (sConfigurationChangedReceiver == null) { 402a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein sConfigurationChangedReceiver = new BroadcastReceiver() { 403a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein @Override 404a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein public void onReceive(Context context, Intent intent) { 405a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein STAR_OFF = null; 406a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein getItemViewResources(context); 407a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein } 408a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein }; 409a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein context.registerReceiver(sConfigurationChangedReceiver, new IntentFilter( 410a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein Intent.ACTION_CONFIGURATION_CHANGED)); 411a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein } 4124758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang if (STAR_OFF == null) { 413a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein final Resources res = context.getResources(); 4146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize static bitmaps. 415eb58a092961773a8da67c0e0dd5770346381d938Andrew Sapperstein STAR_OFF = BitmapFactory.decodeResource(res, R.drawable.ic_star_outline_20dp); 416eb58a092961773a8da67c0e0dd5770346381d938Andrew Sapperstein STAR_ON = BitmapFactory.decodeResource(res, R.drawable.ic_star_20dp); 417091484627a207de3fceea8727439082b022748aeJames Lemieux ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attach_file_18dp); 4184a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang ONLY_TO_ME = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_double); 4194a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_single); 4204a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang IMPORTANT_ONLY_TO_ME = BitmapFactory.decodeResource(res, 4214a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang R.drawable.ic_email_caret_double_important_unread); 4224a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang IMPORTANT_TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, 4234a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang R.drawable.ic_email_caret_single_important_unread); 42417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein IMPORTANT = BitmapFactory.decodeResource(res, 4254a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang R.drawable.ic_email_caret_none_important_unread); 42654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_REPLIED = 42754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_holo_light); 42854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_FORWARDED = 42954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_forward_holo_light); 43054467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira STATE_REPLIED_AND_FORWARDED = 43154467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_forward_holo_light); 4328d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira STATE_CALENDAR_INVITE = 4338d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira BitmapFactory.decodeResource(res, R.drawable.ic_badge_invite_holo_light); 4340532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao FOCUSED_CONVERSATION_HIGHLIGHT = res.getDrawable( 435f58e4c3c942033fce12b5f75f9e4d9e708c9ea6aAndy Huang R.drawable.visible_conversation_highlight); 4366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 4376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize colors. 438371e0ad5de82585a0a0613ac5410c9ead65613caTony Mantler sActivatedTextSpan = CharacterStyle.wrap(new ForegroundColorSpan( 4395750406080090ed22bf93036525c2ff30f41b28aJames Lemieux res.getColor(R.color.senders_text_color))); 4405750406080090ed22bf93036525c2ff30f41b28aJames Lemieux sSendersTextColor = res.getColor(R.color.senders_text_color); 441a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein sSubjectTextUnreadSpan = new TextAppearanceSpan(context, 4426a4c4f62db0ddf6660d889bf1f21e37d25a99363mindyp R.style.SubjectAppearanceUnreadStyle); 443f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux sSubjectTextReadSpan = new TextAppearanceSpan( 444f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux context, R.style.SubjectAppearanceReadStyle); 445f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux 446a5dfa98bbafd402fa15c32efe4a0b55ebdfd7d11Andrew Sapperstein sBadgeTextSpan = new TextAppearanceSpan(context, R.style.BadgeTextStyle); 447be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein sBadgeBackgroundSpan = new BackgroundColorSpan( 448be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein res.getColor(R.color.badge_background_color)); 4491c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux sDateTextColorRead = res.getColor(R.color.date_text_color_read); 4501c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux sDateTextColorUnread = res.getColor(R.color.date_text_color_unread); 451ce2c0a15773909bfd09935673c4974b5922eba68Alice Yang sStarTouchSlop = res.getDimensionPixelSize(R.dimen.star_touch_slop); 452ce2c0a15773909bfd09935673c4974b5922eba68Alice Yang sSenderImageTouchSlop = res.getDimensionPixelSize(R.dimen.sender_image_touch_slop); 453067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira sShrinkAnimationDuration = res.getInteger(R.integer.shrink_animation_duration); 454067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira sSlideAnimationDuration = res.getInteger(R.integer.slide_animation_duration); 4556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Initialize static color. 456ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sSendersSplitToken = res.getString(R.string.senders_split_token); 457ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sElidedPaddingToken = res.getString(R.string.elided_padding_token); 458d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp sScrollSlop = res.getInteger(R.integer.swipeScrollSlop); 459ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao sFoldersMaxCount = res.getInteger(R.integer.conversation_list_max_folder_count); 460a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei sCabAnimationDuration = res.getInteger(R.integer.conv_item_view_cab_anim_duration); 461be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein sBadgePaddingExtraWidth = res.getDimensionPixelSize(R.dimen.badge_padding_extra_width); 462be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein sBadgeRoundedCornerRadius = 463be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein res.getDimensionPixelSize(R.dimen.badge_rounded_corner_radius); 464a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux sDividerPaint.setColor(res.getColor(R.color.divider_color)); 465cace3194e9b7b0e2b6554bda2fa8b2f98da04175James Lemieux sDividerHeight = res.getDimensionPixelSize(R.dimen.divider_height); 466a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei } 4676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 4686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 469aa76bdfae889b995395a7636742128b3585727f9Mark Wei public void bind(final Conversation conversation, final ControllableActivity activity, 470ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final ConversationCheckedSet set, final Folder folder, 4710e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux final int checkboxOrSenderImage, 47217646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein final boolean swipeEnabled, final boolean importanceMarkersEnabled, 473f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao final boolean showChevronsEnabled, final AnimatedAdapter adapter) { 474479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("CIVC.bind"); 4753dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao bind(ConversationItemViewModel.forConversation(mAccount.getEmailAddress(), conversation), 4763dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao activity, null /* conversationItemAreaClickListener */, 4770e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux set, folder, checkboxOrSenderImage, swipeEnabled, importanceMarkersEnabled, 4780e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux showChevronsEnabled, adapter, -1 /* backgroundOverrideResId */, 479a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux null /* photoBitmap */, false /* useFullMargins */, true /* mDividerEnabled */); 480103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy Utils.traceEndSection(); 481103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } 482103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy 483103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy public void bindAd(final ConversationItemViewModel conversationItemViewModel, 484103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy final ControllableActivity activity, 485d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy final ConversationItemAreaClickListener conversationItemAreaClickListener, 486d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy final Folder folder, final int checkboxOrSenderImage, final AnimatedAdapter adapter, 487cc8ed8dca4080649c4fff3f6b0e3b35dbf0145f2Scott Kennedy final int backgroundOverrideResId, final Bitmap photoBitmap) { 488103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy Utils.traceBeginSection("CIVC.bindAd"); 489a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei bind(conversationItemViewModel, activity, conversationItemAreaClickListener, null /* set */, 4900e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux folder, checkboxOrSenderImage, true /* swipeEnabled */, 49117646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein false /* importanceMarkersEnabled */, false /* showChevronsEnabled */, 492a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux adapter, backgroundOverrideResId, photoBitmap, true /* useFullMargins */, 493a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux false /* mDividerEnabled */); 494479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 495acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira } 496acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira 497aa76bdfae889b995395a7636742128b3585727f9Mark Wei private void bind(final ConversationItemViewModel header, final ControllableActivity activity, 498d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy final ConversationItemAreaClickListener conversationItemAreaClickListener, 499ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final ConversationCheckedSet set, final Folder folder, 5000e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux final int checkboxOrSenderImage, 50117646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein boolean swipeEnabled, final boolean importanceMarkersEnabled, 50217646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein final boolean showChevronsEnabled, final AnimatedAdapter adapter, 503be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein final int backgroundOverrideResId, final Bitmap photoBitmap, 504a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux final boolean useFullMargins, final boolean dividerEnabled) { 505103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy mBackgroundOverrideResId = backgroundOverrideResId; 506103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy mPhotoBitmap = photoBitmap; 507d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mConversationItemAreaClickListener = conversationItemAreaClickListener; 508a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux mDividerEnabled = dividerEnabled; 509103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy 510f832d5f8b490e184d0c9cd70bba8f32ed29ff51amindyp if (mHeader != null) { 511a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("unbind"); 512a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei final boolean newlyBound = header.conversation.id != mHeader.conversation.id; 513479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // If this was previously bound to a different conversation, remove any contact photo 514479505d71969e26b0785d8e0e1b81108731cf827Mark Wei // manager requests. 5153dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (newlyBound || (!mHeader.displayableNames.equals(header.displayableNames))) { 5165f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux mSendersImageView.getContactDrawable().unbind(); 517479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 518479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 519a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei if (newlyBound) { 5208c843a7610fed6ecd8e4e6d9f43c4eea2a7ff3a1Scott Kennedy // Stop the photo flip animation 521ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final boolean showSenders = !mChecked; 522a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView.reset(showSenders); 5238c843a7610fed6ecd8e4e6d9f43c4eea2a7ff3a1Scott Kennedy } 524a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 525f832d5f8b490e184d0c9cd70bba8f32ed29ff51amindyp } 526b53fe05fb867685d0d3f2f37daf0f93bc6488dedAndy Huang mCoordinates = null; 527acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira mHeader = header; 528e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira mActivity = activity; 529ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedConversationSet = set; 530ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet != null) { 531ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedConversationSet.addObserver(this); 532f1566b1e77e9d7ac66ebb47897b5c652e2b18943Andrew Sapperstein } 533b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira mDisplayedFolder = folder; 53498aeca3818c3b696f304c1bfb5657a1e1f277a04Paul Westbrook mStarEnabled = folder != null && !folder.isTrash(); 535f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira mSwipeEnabled = swipeEnabled; 536bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook mAdapter = adapter; 537a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 538a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("drawables"); 5395f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux mSendersImageView.getContactDrawable().setBitmapCache(mAdapter.getSendersImagesCache()); 5405f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux mSendersImageView.getContactDrawable().setContactResolver(mAdapter.getContactResolver()); 541a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 542fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 5434758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang if (checkboxOrSenderImage == ConversationListIcon.SENDER_IMAGE) { 5444758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang mGadgetMode = ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO; 545fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } else { 5464758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang mGadgetMode = ConversationItemViewCoordinates.GADGET_NONE; 547fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 548fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 549a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("folder displayer"); 550fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang // Initialize folder displayer. 551fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mHeader.folderDisplayer == null) { 5524eb909e1ef9656dfc06d2518842357827dcfb068Jin Cao mHeader.folderDisplayer = new ConversationItemFolderDisplayer(mContext, 5534eb909e1ef9656dfc06d2518842357827dcfb068Jin Cao mAdapter.getBidiFormatter()); 554fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } else { 555fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mHeader.folderDisplayer.reset(); 556fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 557a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 558fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 559fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int ignoreFolderType; 560fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mDisplayedFolder.isInbox()) { 561fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang ignoreFolderType = FolderType.INBOX; 562fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } else { 563fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang ignoreFolderType = -1; 564fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 565fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 566a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("load folders"); 567259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy mHeader.folderDisplayer.loadConversationFolders(mHeader.conversation, 568259df5b9e11908c8ef7c91483924891dd96b3c27Scott Kennedy mDisplayedFolder.folderUri, ignoreFolderType); 569a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 570fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 571be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein if (mHeader.showDateText) { 572a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("relative time"); 573103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy mHeader.dateText = DateUtils.getRelativeTimeSpanString(mContext, 574103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy mHeader.conversation.dateMs); 575a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 576103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } else { 577be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein mHeader.dateText = ""; 578103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } 579fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 580a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("config setup"); 581fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mConfig = new ConversationItemViewCoordinates.Config() 5824758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang .withGadget(mGadgetMode) 583be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein .setUseFullMargins(useFullMargins); 584fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (header.folderDisplayer.hasVisibleFolders()) { 585fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mConfig.showFolders(); 586fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 587fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (header.hasBeenForwarded || header.hasBeenRepliedTo || header.isInvite) { 588fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mConfig.showReplyState(); 589fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 590fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mHeader.conversation.color != 0) { 591fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mConfig.showColorBlock(); 592fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 593a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 59417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein // Importance markers and chevrons (personal level indicators). 5954a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang mHeader.personalLevelBitmap = null; 59617646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein final int personalLevel = mHeader.conversation.personalLevel; 59717646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein final boolean isImportant = 59817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mHeader.conversation.priority == UIProvider.ConversationPriority.IMPORTANT; 59917646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein final boolean useImportantMarkers = isImportant && importanceMarkersEnabled; 60017646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein if (showChevronsEnabled && 60117646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein personalLevel == UIProvider.ConversationPersonalLevel.ONLY_TO_ME) { 60217646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_ONLY_TO_ME 60317646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein : ONLY_TO_ME; 60417646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein } else if (showChevronsEnabled && 60517646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein personalLevel == UIProvider.ConversationPersonalLevel.TO_ME_AND_OTHERS) { 60617646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_TO_ME_AND_OTHERS 60717646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein : TO_ME_AND_OTHERS; 60817646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein } else if (useImportantMarkers) { 60917646055214b9ab3abc2553379bf046ca3e53fb2Andrew Sapperstein mHeader.personalLevelBitmap = IMPORTANT; 6104a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang } 6114a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang if (mHeader.personalLevelBitmap != null) { 6124a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang mConfig.showPersonalIndicator(); 6134a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang } 614a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 615fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 616a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("content description"); 617ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp setContentDescription(); 618a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 619f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira requestLayout(); 620f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira } 621f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira 62279c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang @Override 623f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei protected void onDetachedFromWindow() { 624f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei super.onDetachedFromWindow(); 625f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei 626ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet != null) { 627ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedConversationSet.removeObserver(this); 628f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei } 629f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei } 630f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei 631f4ff7675cbc23c56b9b35f9f26574afef030f0afMark Wei @Override 632a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public void invalidateDrawable(final Drawable who) { 63379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang boolean handled = false; 63479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang if (mCoordinates != null) { 6350e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux if (mSendersImageView.equals(who)) { 636a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei final Rect r = new Rect(who.getBounds()); 637a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei r.offset(mCoordinates.contactImagesX, mCoordinates.contactImagesY); 638a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei ConversationItemView.this.invalidate(r.left, r.top, r.right, r.bottom); 639a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei handled = true; 64079c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 64179c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 64279c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang if (!handled) { 64379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang super.invalidateDrawable(who); 64479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 64579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 64679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 647866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 648866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Get the Conversation object associated with this view. 649866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 650732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang public Conversation getConversation() { 651732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang return mHeader.conversation; 652732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang } 653732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang 6546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static void startTimer(String tag) { 6556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null) { 6566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.start(tag); 6576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private static void pauseTimer(String tag) { 6616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null) { 6626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.pause(tag); 6636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 667fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 668479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("CIVC.measure"); 669fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int wSize = MeasureSpec.getSize(widthMeasureSpec); 6706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 6710d1ed12c6e70f4204ff28092ed51ce540f9f3f67Vikram Aggarwal final int currentMode = mActivity.getViewMode().getMode(); 672fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (wSize != mViewWidth || mPreviousMode != currentMode) { 673fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mViewWidth = wSize; 6740d1ed12c6e70f4204ff28092ed51ce540f9f3f67Vikram Aggarwal mPreviousMode = currentMode; 6756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 6766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.viewWidth = mViewWidth; 677fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 6784958af88fe77f0c5c92ab0f7e1e6cbba645c3180James Lemieux mConfig.updateWidth(wSize).setLayoutDirection(ViewCompat.getLayoutDirection(this)); 679fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 6806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Resources res = getResources(); 6816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen); 682fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 683fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mCoordinates = ConversationItemViewCoordinates.forConfig(mContext, mConfig, 684fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mAdapter.getCoordinatesCache()); 685fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 686103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy if (mPhotoBitmap != null) { 687c12da4a53eee911765975f0d8afe62f749806b60Jin Cao mPhotoRect.set(0, 0, mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight); 688103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } 689103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy 690370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final int h = (mAnimatedHeightFraction != 1.0f) ? 691370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang Math.round(mAnimatedHeightFraction * mCoordinates.height) : mCoordinates.height; 692fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang setMeasuredDimension(mConfig.getWidth(), h); 693479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 694fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 695fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 696fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang @Override 697fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 698fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang startTimer(PERF_TAG_LAYOUT); 699f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceBeginSection("CIVC.layout"); 700fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 701fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang super.onLayout(changed, left, top, right, bottom); 702fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 7032229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei Utils.traceBeginSection("text and bitmaps"); 7046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira calculateTextsAndBitmaps(); 7052229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei Utils.traceEndSection(); 7062229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei 7072229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei Utils.traceBeginSection("coordinates"); 7086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira calculateCoordinates(); 7092229eddfba6f7517c43ef49ee67c50c24d4b961aMark Wei Utils.traceEndSection(); 710167bddc283a66f210e0484eeca609f4e7f35dac4mindyp 711167bddc283a66f210e0484eeca609f4e7f35dac4mindyp // Subject. 712a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("subject"); 7139e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy createSubject(mHeader.unread); 714167bddc283a66f210e0484eeca609f4e7f35dac4mindyp 715928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux createSnippet(); 716be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 7173b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy if (!mHeader.isLayoutValid()) { 718ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp setContentDescription(); 719dc0617f3478b21dd3324ab10b8c433517ae95460mindyp } 7203b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy mHeader.validate(); 721a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 7226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 7236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira pauseTimer(PERF_TAG_LAYOUT); 7246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (sTimer != null && ++sLayoutCount >= PERF_LAYOUT_ITERATIONS) { 7256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer.dumpResults(); 7266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sTimer = new Timer(); 7276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sLayoutCount = 0; 7286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 729f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceEndSection(); 7306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 732ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp private void setContentDescription() { 7332cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao String foldersDesc = null; 7342cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao if (mHeader != null && mHeader.folderDisplayer != null) { 7352cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao foldersDesc = mHeader.folderDisplayer.getFoldersDesc(); 7362cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao } 7372cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao 738ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp if (mActivity.isAccessibilityEnabled()) { 739ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp mHeader.resetContentDescription(); 7402cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao setContentDescription(mHeader.getContentDescription( 7412cff0881131d3cd4469d3494a3f7bf0ee3f2f09eJin Cao mContext, mDisplayedFolder.shouldShowRecipients(), foldersDesc)); 742ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp } 743ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp } 744ca87de41285bde382a894b6cb2d13c112c5d7a2fmindyp 7456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 7466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira public void setBackgroundResource(int resourceId) { 747479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("set background resource"); 7486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira Drawable drawable = mBackgrounds.get(resourceId); 7496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (drawable == null) { 7506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira drawable = getResources().getDrawable(resourceId); 751be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein final int insetPadding = mHeader.insetPadding; 752be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein if (insetPadding > 0) { 753be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein drawable = new InsetDrawable(drawable, insetPadding); 754be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 7556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mBackgrounds.put(resourceId, drawable); 7566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (getBackground() != drawable) { 758f5de30d2bccf2e5eaace2424ad91784c43d42075Jin Cao super.setBackgroundDrawable(drawable); 7596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 760479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 7616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 7626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 7636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void calculateTextsAndBitmaps() { 7646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 765f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp 766ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet != null) { 767ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao setChecked(mCheckedConversationSet.contains(mHeader.conversation)); 768d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal } 7694758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang mHeader.gadgetMode = mGadgetMode; 7706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 771be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein updateBackground(); 7726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 773f27e08e98db1496610c9f216ef6eeb26c39c2da3Scott Kennedy mHeader.hasDraftMessage = mHeader.conversation.numDrafts() > 0; 774f27e08e98db1496610c9f216ef6eeb26c39c2da3Scott Kennedy 7758335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp // Parse senders fragments. 7763b2039afbcd8465ab829ecda8a5b207e988e773cScott Kennedy if (mHeader.preserveSendersText) { 7773b2039afbcd8465ab829ecda8a5b207e988e773cScott Kennedy // This is a special view that doesn't need special sender formatting 7783b2039afbcd8465ab829ecda8a5b207e988e773cScott Kennedy mHeader.sendersDisplayText = new SpannableStringBuilder(mHeader.sendersText); 7793b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux loadImages(); 7803b2039afbcd8465ab829ecda8a5b207e988e773cScott Kennedy } else if (mHeader.conversation.conversationInfo != null) { 7818335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp Context context = getContext(); 7828335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp mHeader.messageInfoString = SendersView 783d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy .createMessageInfo(context, mHeader.conversation, true); 7844958af88fe77f0c5c92ab0f7e1e6cbba645c3180James Lemieux final int maxChars = ConversationItemViewCoordinates.getSendersLength(context, 7854958af88fe77f0c5c92ab0f7e1e6cbba645c3180James Lemieux mHeader.conversation.hasAttachments); 7863dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 7873dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao mHeader.mSenderAvatarModel.clear(); 7883dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao mHeader.displayableNames.clear(); 7893dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao mHeader.styledNames.clear(); 7903b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux 79188acafa03a87f5c84b959697d13b81df8f11a96emindyp SendersView.format(context, mHeader.conversation.conversationInfo, 7923b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux mHeader.messageInfoString.toString(), maxChars, mHeader.styledNames, 7933dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao mHeader.displayableNames, mHeader.mSenderAvatarModel, 794c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux mAccount, mDisplayedFolder.shouldShowRecipients(), true); 795f27e08e98db1496610c9f216ef6eeb26c39c2da3Scott Kennedy 796d198fa7ddb2d0c730847af34f06aa2e940b2537dMark Wei // If we have displayable senders, load their thumbnails 7973b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux loadImages(); 7988335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp } else { 799edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler LogUtils.wtf(LOG_TAG, "Null conversationInfo"); 8008335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp } 8018335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp 8023b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy if (mHeader.isLayoutValid()) { 803f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 804f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp return; 805f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp } 806f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp startTimer(PERF_TAG_CALCULATE_FOLDERS); 807f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp 808f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp 809f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp pauseTimer(PERF_TAG_CALCULATE_FOLDERS); 810f2caf91209e4e2d4182d6b379a3cd79eed81af71mindyp 8116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Paper clip icon. 8126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.paperclip = null; 813732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang if (mHeader.conversation.hasAttachments) { 8146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira mHeader.paperclip = ATTACHMENT; 8156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 816d198fa7ddb2d0c730847af34f06aa2e940b2537dMark Wei 8176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT); 8186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 8198335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp pauseTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT); 8208335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS); 8218335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp } 8226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 823fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang // FIXME(ath): maybe move this to bind(). the only dependency on layout is on tile W/H, which 824fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang // is immutable. 8253b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux private void loadImages() { 826a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei if (mGadgetMode != ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO 8273dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao || mHeader.mSenderAvatarModel.isNotPopulated()) { 828a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return; 829a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei } 830a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei if (mCoordinates.contactImagesWidth <= 0 || mCoordinates.contactImagesHeight <= 0) { 831a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei LogUtils.w(LOG_TAG, 8324958af88fe77f0c5c92ab0f7e1e6cbba645c3180James Lemieux "Contact image width(%d) or height(%d) is 0", 8334958af88fe77f0c5c92ab0f7e1e6cbba645c3180James Lemieux mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight); 834a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei return; 835a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei } 836479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 837a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView 838a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei .setBounds(0, 0, mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight); 839479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 8405f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux Utils.traceBeginSection("load sender image"); 8415f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux final ContactDrawable drawable = mSendersImageView.getContactDrawable(); 8425f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux drawable.setDecodeDimensions(mCoordinates.contactImagesWidth, 8435f79af7b356c3a8ecd8cd77fcbde673de9023b50James Lemieux mCoordinates.contactImagesHeight); 8443dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao drawable.bind(mHeader.mSenderAvatarModel.getName(), 8453dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao mHeader.mSenderAvatarModel.getEmailAddress()); 846a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 8476d11c8fbca5d54a013d78c85d6eb28f590093e3cmindyp } 8486d11c8fbca5d54a013d78c85d6eb28f590093e3cmindyp 849fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang private static int makeExactSpecForSize(int size) { 850fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 851fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 852fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 853fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang private static void layoutViewExactly(View v, int w, int h) { 854fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang v.measure(makeExactSpecForSize(w), makeExactSpecForSize(h)); 855fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang v.layout(0, 0, w, h); 856fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang } 857fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 85810ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux private void layoutParticipantText(SpannableStringBuilder participantText) { 85910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux if (participantText != null) { 8608335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp if (isActivated() && showActivatedText()) { 86110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux participantText.setSpan(sActivatedTextSpan, 0, 8628335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp mHeader.styledMessageInfoStringOffset, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 8638335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp } else { 86410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux participantText.removeSpan(sActivatedTextSpan); 8658335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp } 866d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang 867fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int w = mSendersWidth; 868fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int h = mCoordinates.sendersHeight; 869fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSendersTextView.setLayoutParams(new ViewGroup.LayoutParams(w, h)); 870fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSendersTextView.setMaxLines(mCoordinates.sendersLineCount); 871fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSendersTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCoordinates.sendersFontSize); 872fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang layoutViewExactly(mSendersTextView, w, h); 873fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 87410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux mSendersTextView.setText(participantText); 875c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira } 8766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 8776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 8789e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy private void createSubject(final boolean isUnread) { 879928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final String badgeText = mHeader.badgeText == null ? "" : mHeader.badgeText; 88094033deeb31df739a27fce15887a3f0a2e808b12James Lemieux String subject = filterTag(getContext(), mHeader.conversation.subject); 88131702cbfde9055e528ac43addaf1ab0eb791d900James Lemieux subject = mAdapter.getBidiFormatter().unicodeWrap(subject); 88294033deeb31df739a27fce15887a3f0a2e808b12James Lemieux subject = Conversation.getSubjectForDisplay(mContext, badgeText, subject); 88394033deeb31df739a27fce15887a3f0a2e808b12James Lemieux final Spannable displayedStringBuilder = new SpannableString(subject); 884c046e4a310462aa6998a34ff50439eb5e2508d85mindyp 88531702cbfde9055e528ac43addaf1ab0eb791d900James Lemieux // since spans affect text metrics, add spans to the string before measure/layout or eliding 886be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 887be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein final int badgeTextLength = formatBadgeText(displayedStringBuilder, badgeText); 888be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 889c244f29b6f9af500fedf8aad48db4c80df52c5c1Scott Kennedy if (!TextUtils.isEmpty(subject)) { 890c244f29b6f9af500fedf8aad48db4c80df52c5c1Scott Kennedy displayedStringBuilder.setSpan(TextAppearanceSpan.wrap( 891be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein isUnread ? sSubjectTextUnreadSpan : sSubjectTextReadSpan), 892961aada3d12af6cd31ae620e53358beb7e5d5062James Lemieux badgeTextLength, subject.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 893c244f29b6f9af500fedf8aad48db4c80df52c5c1Scott Kennedy } 8948335d37d0e6b6e06ba4666223945c2a3f24103c1mindyp if (isActivated() && showActivatedText()) { 895be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein displayedStringBuilder.setSpan(sActivatedTextSpan, badgeTextLength, 896be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein displayedStringBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 8975d6773c773401a259e6b6db957c34f36c508816bAndy Huang } 8985d6773c773401a259e6b6db957c34f36c508816bAndy Huang 8995d6773c773401a259e6b6db957c34f36c508816bAndy Huang final int subjectWidth = mCoordinates.subjectWidth; 900fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang final int subjectHeight = mCoordinates.subjectHeight; 901fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSubjectTextView.setLayoutParams(new ViewGroup.LayoutParams(subjectWidth, subjectHeight)); 902fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSubjectTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCoordinates.subjectFontSize); 903fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang layoutViewExactly(mSubjectTextView, subjectWidth, subjectHeight); 904fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang 905fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mSubjectTextView.setText(displayedStringBuilder); 9066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 9076f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 908928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux private void createSnippet() { 909928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final String snippet = mHeader.conversation.getSnippet(); 910928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final Spannable displayedStringBuilder = new SpannableString(snippet); 911be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 91264f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux // measure the width of the folders which overlap the snippet view 913ff404bb78dec989c1660434915b1b027a2d86bf3Jin Cao final int folderWidth = mHeader.folderDisplayer.measureFolders(mCoordinates); 91464f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux 91564f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux // size the snippet view by subtracting the folder width from the maximum snippet width 91664f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux final int snippetWidth = mCoordinates.maxSnippetWidth - folderWidth; 917928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final int snippetHeight = mCoordinates.snippetHeight; 918928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.setLayoutParams(new ViewGroup.LayoutParams(snippetWidth, snippetHeight)); 919928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCoordinates.snippetFontSize); 920928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux layoutViewExactly(mSnippetTextView, snippetWidth, snippetHeight); 921be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 922928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.setText(displayedStringBuilder); 923be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 924be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 925be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private int formatBadgeText(Spannable displayedStringBuilder, String badgeText) { 926be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein final int badgeTextLength = (badgeText != null) ? badgeText.length() : 0; 927be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein if (!TextUtils.isEmpty(badgeText)) { 928be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein displayedStringBuilder.setSpan(TextAppearanceSpan.wrap(sBadgeTextSpan), 929be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 0, badgeTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 930be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein displayedStringBuilder.setSpan(TextAppearanceSpan.wrap(sBadgeBackgroundSpan), 931be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 0, badgeTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 932be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein displayedStringBuilder.setSpan(new BadgeSpan(displayedStringBuilder, this), 933be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 0, badgeTextLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 934be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 935be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 936be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein return badgeTextLength; 937be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 938be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 939be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein // START BadgeSpan.BadgeSpanDimensions override 940be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 941be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein @Override 942be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein public int getHorizontalPadding() { 943be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein return sBadgePaddingExtraWidth; 944be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 945be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 946be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein @Override 947be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein public float getRoundedCornerRadius() { 948be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein return sBadgeRoundedCornerRadius; 949be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 950be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 951be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein // END BadgeSpan.BadgeSpanDimensions override 952be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 9530b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira private boolean showActivatedText() { 95497f573d41eb1ab6e0b3683f081452391cf2a76aeVikram Aggarwal // For activated elements in tablet in conversation mode, we show an activated color, since 95597f573d41eb1ab6e0b3683f081452391cf2a76aeVikram Aggarwal // the background is dark blue for activated versus gray for non-activated. 9567fdf34185f0d41bdebf25bcf6d14927b16658136Andy Huang return mTabletDevice && !mListCollapsible; 9570b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira } 9580b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira 9596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira private void calculateCoordinates() { 9606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira startTimer(PERF_TAG_CALCULATE_COORDINATES); 9616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 9626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTextSize(mCoordinates.dateFontSize); 9636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 96452b280a82df262f62632bd12bba84b4752f14634Scott Kennedy 965a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein final boolean isRtl = ViewUtils.isViewRtl(this); 966a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein 967a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mDateWidth = (int) sPaint.measureText( 968a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mHeader.dateText != null ? mHeader.dateText.toString() : ""); 96952b280a82df262f62632bd12bba84b4752f14634Scott Kennedy if (mHeader.infoIcon != null) { 970a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mInfoIconX = (isRtl) ? mCoordinates.infoIconX : 971a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mCoordinates.infoIconXRight - mHeader.infoIcon.getWidth(); 97252b280a82df262f62632bd12bba84b4752f14634Scott Kennedy 97352b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // If we have an info icon, we start drawing the date text: 97452b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // At the end of the date TextView minus the width of the date text 975a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // In RTL mode, we just use dateX 976a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mDateX = (isRtl) ? mCoordinates.dateX : mCoordinates.dateXRight - mDateWidth; 97752b280a82df262f62632bd12bba84b4752f14634Scott Kennedy } else { 97852b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // If there is no info icon, we start drawing the date text: 97952b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // At the end of the info icon ImageView minus the width of the date text 98052b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // We use the info icon ImageView for positioning, since we want the date text to be 98152b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // at the right, since there is no info icon 982a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // In RTL, we just use infoIconX 9831c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux mDateX = (isRtl) ? mCoordinates.infoIconX : mCoordinates.infoIconXRight - mDateWidth; 98452b280a82df262f62632bd12bba84b4752f14634Scott Kennedy } 9856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 986a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // The paperclip is drawn starting at the start of the date text minus 987a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // the width of the paperclip and the date padding. 988a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // In RTL mode, it is at the end of the date (mDateX + mDateWidth) plus the 989a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // start date padding. 990a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mPaperclipX = (isRtl) ? mDateX + mDateWidth + mCoordinates.datePaddingStart : 991a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mDateX - ATTACHMENT.getWidth() - mCoordinates.datePaddingStart; 9926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 993928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // In normal mode, the senders x and width is based 994928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // on where the date/attachment icon start. 995928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux final int dateAttachmentStart; 996928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // Have this end near the paperclip or date, not the folders. 997928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux if (mHeader.paperclip != null) { 998928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // If there is a paperclip, the date/attachment start is at the start 999928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // of the paperclip minus the paperclip padding. 1000928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // In RTL, it is at the end of the paperclip plus the paperclip padding. 1001928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux dateAttachmentStart = (isRtl) ? 1002928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mPaperclipX + ATTACHMENT.getWidth() + mCoordinates.paperclipPaddingStart 1003928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux : mPaperclipX - mCoordinates.paperclipPaddingStart; 10043fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira } else { 1005928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // If no paperclip, just use the start of the date minus the date padding start. 1006928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // In RTL mode, this is just the paperclipX. 1007928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux dateAttachmentStart = (isRtl) ? 1008928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mPaperclipX : mDateX - mCoordinates.datePaddingStart; 1009928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux } 1010928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // Senders width is the dateAttachmentStart - sendersX. 1011928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // In RTL, it is sendersWidth + sendersX - dateAttachmentStart. 1012928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSendersWidth = (isRtl) ? 1013928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mCoordinates.sendersWidth + mCoordinates.sendersX - dateAttachmentStart 1014928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux : dateAttachmentStart - mCoordinates.sendersX; 1015928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSendersX = (isRtl) ? dateAttachmentStart : mCoordinates.sendersX; 10166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 10176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Second pass to layout each fragment. 1018bcab7611959549a955be8a30115d6a4c937afd24Andy Huang sPaint.setTextSize(mCoordinates.sendersFontSize); 1019bcab7611959549a955be8a30115d6a4c937afd24Andy Huang sPaint.setTypeface(Typeface.DEFAULT); 1020bcab7611959549a955be8a30115d6a4c937afd24Andy Huang 102142b362587928704ea17b0a09a5e4e16037d14491Jin Cao // First pass to calculate width of each fragment. 102242b362587928704ea17b0a09a5e4e16037d14491Jin Cao if (mSendersWidth < 0) { 102342b362587928704ea17b0a09a5e4e16037d14491Jin Cao mSendersWidth = 0; 102442b362587928704ea17b0a09a5e4e16037d14491Jin Cao } 1025a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein 102642b362587928704ea17b0a09a5e4e16037d14491Jin Cao // sendersDisplayText is only set when preserveSendersText is true. 102742b362587928704ea17b0a09a5e4e16037d14491Jin Cao if (mHeader.preserveSendersText) { 1028b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mHeader.sendersDisplayLayout = new StaticLayout(mHeader.sendersDisplayText, sPaint, 1029b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira mSendersWidth, Alignment.ALIGN_NORMAL, 1, 0, true); 103042b362587928704ea17b0a09a5e4e16037d14491Jin Cao } else { 103142b362587928704ea17b0a09a5e4e16037d14491Jin Cao final SpannableStringBuilder participantText = elideParticipants(mHeader.styledNames); 103242b362587928704ea17b0a09a5e4e16037d14491Jin Cao layoutParticipantText(participantText); 1033b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 1034b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 1035b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira pauseTimer(PERF_TAG_CALCULATE_COORDINATES); 1036b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 1037b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 103810ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux // The rules for displaying elided participants are as follows: 103958ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // 1) If there is message info (either a COUNT or DRAFT info to display), it MUST be shown 104058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // 2) If senders do not fit, ellipsize the last one that does fit, and stop 104158ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // appending new senders 104210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux SpannableStringBuilder elideParticipants(List<SpannableString> parts) { 104310ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final SpannableStringBuilder builder = new SpannableStringBuilder(); 104484cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira float totalWidth = 0; 1045b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira boolean ellipsize = false; 104684cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira float width; 104710ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux boolean skipToHeader = false; 104810ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux 104910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux // start with "To: " if we're showing recipients 105010ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux if (mDisplayedFolder.shouldShowRecipients() && !parts.isEmpty()) { 105110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final SpannableString toHeader = SendersView.getFormattedToHeader(); 105210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux CharacterStyle[] spans = toHeader.getSpans(0, toHeader.length(), 105310ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux CharacterStyle.class); 105410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux // There is only 1 character style span; make sure we apply all the 105510ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux // styles to the paint object before measuring. 105610ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux if (spans.length > 0) { 105710ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux spans[0].updateDrawState(sPaint); 105810ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux } 105910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux totalWidth += sPaint.measureText(toHeader.toString()); 106010ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux builder.append(toHeader); 106110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux skipToHeader = true; 106210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux } 106310ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux 106410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final SpannableStringBuilder messageInfoString = mHeader.messageInfoString; 106542b362587928704ea17b0a09a5e4e16037d14491Jin Cao if (!TextUtils.isEmpty(messageInfoString)) { 10660c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira CharacterStyle[] spans = messageInfoString.getSpans(0, messageInfoString.length(), 10670c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira CharacterStyle.class); 10680c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // There is only 1 character style span; make sure we apply all the 10690c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // styles to the paint object before measuring. 10700c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira if (spans.length > 0) { 10710c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira spans[0].updateDrawState(sPaint); 10720c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira } 10730c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira // Paint the message info string to see if we lose space. 10740c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira float messageInfoWidth = sPaint.measureText(messageInfoString.toString()); 10750c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira totalWidth += messageInfoWidth; 10760c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira } 107742b362587928704ea17b0a09a5e4e16037d14491Jin Cao SpannableString prevSender = null; 107842b362587928704ea17b0a09a5e4e16037d14491Jin Cao SpannableString ellipsizedText; 10793b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux for (SpannableString sender : parts) { 1080feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira // There may be null sender strings if there were dupes we had to remove. 1081feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira if (sender == null) { 1082feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira continue; 1083feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira } 108458ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira // No more width available, we'll only show fixed fragments. 108558ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira if (ellipsize) { 108658ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira break; 108758ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira } 10886c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira CharacterStyle[] spans = sender.getSpans(0, sender.length(), CharacterStyle.class); 10896c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira // There is only 1 character style span. 10906c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira if (spans.length > 0) { 10916c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira spans[0].updateDrawState(sPaint); 10926c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira } 10931152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // If there are already senders present in this string, we need to 10941152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // make sure we prepend the dividing token 1095b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (SendersView.sElidedString.equals(sender.toString())) { 1096ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sender = copyStyles(spans, sElidedPaddingToken + sender + sElidedPaddingToken); 109710ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux } else if (!skipToHeader && builder.length() > 0 1098b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira && (prevSender == null || !SendersView.sElidedString.equals(prevSender 1099b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira .toString()))) { 1100ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sender = copyStyles(spans, sSendersSplitToken + sender); 1101b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } else { 110210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux skipToHeader = false; 11031152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira } 110442b362587928704ea17b0a09a5e4e16037d14491Jin Cao prevSender = sender; 110542b362587928704ea17b0a09a5e4e16037d14491Jin Cao 1106ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp if (spans.length > 0) { 1107ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp spans[0].updateDrawState(sPaint); 1108ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp } 11091152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira // Measure the width of the current sender and make sure we have space 1110b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira width = (int) sPaint.measureText(sender.toString()); 1111ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira if (width + totalWidth > mSendersWidth) { 1112b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira // The text is too long, new line won't help. We have to 1113b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira // ellipsize text. 11141152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsize = true; 1115ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp width = mSendersWidth - totalWidth; // ellipsis width? 11161152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsizedText = copyStyles(spans, 11171152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira TextUtils.ellipsize(sender, sPaint, width, TruncateAt.END)); 11181152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira width = (int) sPaint.measureText(ellipsizedText.toString()); 11191152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira } else { 11201152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira ellipsizedText = null; 1121b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 1122b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira totalWidth += width; 1123b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira 1124b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira final CharSequence fragmentDisplayText; 1125b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira if (ellipsizedText != null) { 1126b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira fragmentDisplayText = ellipsizedText; 1127b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } else { 11281152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira fragmentDisplayText = sender; 1129b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 1130b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira builder.append(fragmentDisplayText); 1131b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 113201bb8d91c8ea039518ee07c8ac83e4e42cd81739Mindy Pereira mHeader.styledMessageInfoStringOffset = builder.length(); 113342b362587928704ea17b0a09a5e4e16037d14491Jin Cao if (!TextUtils.isEmpty(messageInfoString)) { 113442b362587928704ea17b0a09a5e4e16037d14491Jin Cao builder.append(messageInfoString); 113542b362587928704ea17b0a09a5e4e16037d14491Jin Cao } 11363b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux return builder; 113784cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira } 113884cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira 11399e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy private static SpannableString copyStyles(CharacterStyle[] spans, CharSequence newText) { 1140d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira SpannableString s = new SpannableString(newText); 1141d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira if (spans != null && spans.length > 0) { 1142d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira s.setSpan(spans[0], 0, s.length(), 0); 1143d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira } 1144d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira return s; 1145d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira } 1146d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira 11476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira /** 11486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * If the subject contains the tag of a mailing-list (text surrounded with 11496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * []), return the subject with that tag ellipsized, e.g. 11506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira * "[android-gmail-team] Hello" -> "[andr...] Hello" 11516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira */ 115289bf7ce646a0ee67e0a8ee10d8834bcf54257d97Andrew Sapperstein public static String filterTag(Context context, String subject) { 11536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira String result = subject; 115489bf7ce646a0ee67e0a8ee10d8834bcf54257d97Andrew Sapperstein String formatString = context.getResources().getString(R.string.filtered_tag); 11556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (!TextUtils.isEmpty(subject) && subject.charAt(0) == '[') { 11566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira int end = subject.indexOf(']'); 11576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira if (end > 0) { 11586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira String tag = subject.substring(1, end); 11596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira result = String.format(formatString, Utils.ellipsize(tag, 7), 11606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira subject.substring(end + 1)); 11616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira return result; 11646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 11656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 11666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira @Override 11676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira protected void onDraw(Canvas canvas) { 11681b87d3f03320eaa897ce5a4712d8bf0910bfd159Paul Westbrook if (mCoordinates == null) { 11691b87d3f03320eaa897ce5a4712d8bf0910bfd159Paul Westbrook LogUtils.e(LOG_TAG, "null coordinates in ConversationItemView#onDraw"); 11701b87d3f03320eaa897ce5a4712d8bf0910bfd159Paul Westbrook return; 11711b87d3f03320eaa897ce5a4712d8bf0910bfd159Paul Westbrook } 11721b87d3f03320eaa897ce5a4712d8bf0910bfd159Paul Westbrook 1173f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceBeginSection("CIVC.draw"); 1174479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 11754758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang // Contact photo 11764758e980c21027ef1a9cacc9847170290b2ae42eAlice Yang if (mGadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO) { 117795f9e1b167f4945adfa4ca62f4b72a102b621794mindyp canvas.save(); 1178a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceBeginSection("draw senders image"); 1179a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei drawSendersImage(canvas); 1180a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei Utils.traceEndSection(); 118195f9e1b167f4945adfa4ca62f4b72a102b621794mindyp canvas.restore(); 11826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 1183479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 11846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Senders. 11858d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank boolean isUnread = mHeader.unread; 1186ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira // Old style senders; apply text colors/ sizes/ styling. 1187850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp canvas.save(); 1188850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp if (mHeader.sendersDisplayLayout != null) { 1189ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira sPaint.setTextSize(mCoordinates.sendersFontSize); 119077d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira sPaint.setTypeface(SendersView.getTypeface(isUnread)); 11915750406080090ed22bf93036525c2ff30f41b28aJames Lemieux sPaint.setColor(sSendersTextColor); 1192a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein canvas.translate(mSendersX, mCoordinates.sendersY 119343ac9a0d56faa5cf72a771468838b4c413c82d6fmindyp + mHeader.sendersDisplayLayout.getTopPadding()); 1194850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp mHeader.sendersDisplayLayout.draw(canvas); 1195ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp } else { 11962598be2e9681c24fb5746f7c5efc963378dccf0amindyp drawSenders(canvas); 1197ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira } 1198d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang canvas.restore(); 11996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1200850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp 12016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Subject. 12026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira sPaint.setTypeface(Typeface.DEFAULT); 12036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.save(); 12042598be2e9681c24fb5746f7c5efc963378dccf0amindyp drawSubject(canvas); 12056f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.restore(); 12066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1207928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux canvas.save(); 1208928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux drawSnippet(canvas); 1209928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux canvas.restore(); 1210be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 1211b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira // Folders. 1212fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mConfig.areFoldersVisible()) { 1213a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mHeader.folderDisplayer.drawFolders(canvas, mCoordinates, ViewUtils.isViewRtl(this)); 1214b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira } 1215b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira 121692939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank // If this folder has a color (combined view/Email), show it here 1217fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mConfig.isColorBlockVisible()) { 121892939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank sFoldersPaint.setColor(mHeader.conversation.color); 121992939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank sFoldersPaint.setStyle(Paint.Style.FILL); 1220fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang canvas.drawRect(mCoordinates.colorBlockX, mCoordinates.colorBlockY, 1221fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mCoordinates.colorBlockX + mCoordinates.colorBlockWidth, 1222fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang mCoordinates.colorBlockY + mCoordinates.colorBlockHeight, sFoldersPaint); 122392939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank } 122492939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank 122554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira // Draw the reply state. Draw nothing if neither replied nor forwarded. 1226fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang if (mConfig.isReplyStateVisible()) { 122754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira if (mHeader.hasBeenRepliedTo && mHeader.hasBeenForwarded) { 122854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_REPLIED_AND_FORWARDED, mCoordinates.replyStateX, 122954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 123054467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } else if (mHeader.hasBeenRepliedTo) { 123154467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_REPLIED, mCoordinates.replyStateX, 123254467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 123354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } else if (mHeader.hasBeenForwarded) { 123454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira canvas.drawBitmap(STATE_FORWARDED, mCoordinates.replyStateX, 123554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira mCoordinates.replyStateY, null); 12368d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira } else if (mHeader.isInvite) { 1237d5ac9c16e8955abe8366fd1185b86d8bd7c5ac60Mindy Pereira canvas.drawBitmap(STATE_CALENDAR_INVITE, mCoordinates.replyStateX, 12388d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira mCoordinates.replyStateY, null); 123954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } 124054467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira } 124154467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira 12424a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang if (mConfig.isPersonalIndicatorVisible()) { 12434a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang canvas.drawBitmap(mHeader.personalLevelBitmap, mCoordinates.personalIndicatorX, 12444a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang mCoordinates.personalIndicatorY, null); 12454a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang } 12464a85e39fbc318359e8a3cacb874df2372fe9d566Andy Huang 124752b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // Info icon 124852b280a82df262f62632bd12bba84b4752f14634Scott Kennedy if (mHeader.infoIcon != null) { 124952b280a82df262f62632bd12bba84b4752f14634Scott Kennedy canvas.drawBitmap(mHeader.infoIcon, mInfoIconX, mCoordinates.infoIconY, sPaint); 125052b280a82df262f62632bd12bba84b4752f14634Scott Kennedy } 125152b280a82df262f62632bd12bba84b4752f14634Scott Kennedy 12526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira // Date. 1253ce59fca1cfad3489bc121e9b58a9c67e765ca35aAndy Huang sPaint.setTextSize(mCoordinates.dateFontSize); 1254ff35c4d206132d389cc5b77c488bd1fd41926e4dJames Lemieux sPaint.setTypeface(isUnread ? SANS_SERIF_BOLD : SANS_SERIF_LIGHT); 12551c6d71b47e7af11b3cf7bd6da4a89594941be968James Lemieux sPaint.setColor(isUnread ? sDateTextColorUnread : sDateTextColorRead); 1256928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux drawText(canvas, mHeader.dateText, mDateX, mCoordinates.dateYBaseline, sPaint); 12576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 125852b280a82df262f62632bd12bba84b4752f14634Scott Kennedy // Paper clip icon. 125952b280a82df262f62632bd12bba84b4752f14634Scott Kennedy if (mHeader.paperclip != null) { 12606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira canvas.drawBitmap(mHeader.paperclip, mPaperclipX, mCoordinates.paperclipY, sPaint); 12616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 12626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1263a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux // Star. 12648afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy if (mStarEnabled) { 12658afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy canvas.drawBitmap(getStarBitmap(), mCoordinates.starX, mCoordinates.starY, sPaint); 12660a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei } 1267d198fa7ddb2d0c730847af34f06aa2e940b2537dMark Wei 1268a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux // Divider. 1269a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux if (mDividerEnabled) { 12704173d7d25b2eb0caa6ec4adc0b3757d96b7eff6bJames Lemieux final int dividerBottomY = getHeight(); 12714173d7d25b2eb0caa6ec4adc0b3757d96b7eff6bJames Lemieux final int dividerTopY = dividerBottomY - sDividerHeight; 1272a7003405a9f66b6a7ee6caf62c6eb746f834c64dJames Lemieux canvas.drawRect(0, dividerTopY, getWidth(), dividerBottomY, sDividerPaint); 12734173d7d25b2eb0caa6ec4adc0b3757d96b7eff6bJames Lemieux } 1274ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao 1275ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao // The focused bar 12760532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao final SwipeableListView listView = getListView(); 1277f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao if (listView != null && listView.isConversationSelected(getConversation())) { 12780532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao final int w = FOCUSED_CONVERSATION_HIGHLIGHT.getIntrinsicWidth(); 1279ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final boolean isRtl = ViewUtils.isViewRtl(this); 1280ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao // This bar is on the right side of the conv list if it's RTL 12810532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao FOCUSED_CONVERSATION_HIGHLIGHT.setBounds( 1282ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao (isRtl) ? getWidth() - w : 0, 0, 1283ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao (isRtl) ? getWidth() : w, getHeight()); 12840532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao FOCUSED_CONVERSATION_HIGHLIGHT.draw(canvas); 1285ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao } 1286ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao 1287f82d6e7342e277f123a04fc82cc841b180655c15Andy Huang Utils.traceEndSection(); 12884f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira } 12894f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira 12900532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao @Override 12910532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao public void setSelected(boolean selected) { 12920532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao // We catch the selected event here instead of using ListView#setOnItemSelectedListener 12930532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao // because when the framework changes selection due to keyboard events, it sets the selected 12940532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao // state, re-draw the affected views, and then call onItemSelected. That approach won't work 12950532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao // because the view won't know about the new selected position during the re-draw. 12960532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao if (selected) { 12970532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao final SwipeableListView listView = getListView(); 12980532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao if (listView != null) { 1299f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao listView.setSelectedConversation(getConversation()); 13000532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao } 13010532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao } 13020532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao super.setSelected(selected); 13030532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao } 13040532b0edb999c6e131bfd1f2e1eccefed049ba49Jin Cao 1305a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei private void drawSendersImage(final Canvas canvas) { 1306a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei if (!mSendersImageView.isFlipping()) { 1307ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final boolean showSenders = !mChecked; 1308a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView.reset(showSenders); 13091fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy } 1310a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei canvas.translate(mCoordinates.contactImagesX, mCoordinates.contactImagesY); 1311103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy if (mPhotoBitmap == null) { 1312a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView.draw(canvas); 1313103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } else { 1314103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy canvas.drawBitmap(mPhotoBitmap, null, mPhotoRect, sPaint); 1315103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy } 13161fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy } 13171fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy 131895f9e1b167f4945adfa4ca62f4b72a102b621794mindyp private void drawSubject(Canvas canvas) { 1319fbc519e976de0c0debd810ed8c7f77de44d136a1Andy Huang canvas.translate(mCoordinates.subjectX, mCoordinates.subjectY); 132095f9e1b167f4945adfa4ca62f4b72a102b621794mindyp mSubjectTextView.draw(canvas); 13216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 13226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 1323928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux private void drawSnippet(Canvas canvas) { 132464f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux // if folders exist, their width will be the max width - actual width 132564f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux final int folderWidth = mCoordinates.maxSnippetWidth - mSnippetTextView.getWidth(); 132664f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux 132764f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux // in RTL layouts we move the snippet to the right so it doesn't overlap the folders 132864f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux final int x = mCoordinates.snippetX + (ViewUtils.isViewRtl(this) ? folderWidth : 0); 132964f56828a81ad7e29cad3a254a6ecdc05c9284e8James Lemieux canvas.translate(x, mCoordinates.snippetY); 1330928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux mSnippetTextView.draw(canvas); 1331be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein } 1332be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein 133395f9e1b167f4945adfa4ca62f4b72a102b621794mindyp private void drawSenders(Canvas canvas) { 1334a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein canvas.translate(mSendersX, mCoordinates.sendersY); 133595f9e1b167f4945adfa4ca62f4b72a102b621794mindyp mSendersTextView.draw(canvas); 1336bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira } 1337bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira 133895f9e1b167f4945adfa4ca62f4b72a102b621794mindyp private Bitmap getStarBitmap() { 133995f9e1b167f4945adfa4ca62f4b72a102b621794mindyp return mHeader.conversation.starred ? STAR_ON : STAR_OFF; 13406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 13416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira 13429e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy private static void drawText(Canvas canvas, CharSequence s, int x, int y, TextPaint paint) { 1343ce59fca1cfad3489bc121e9b58a9c67e765ca35aAndy Huang canvas.drawText(s, 0, s.length(), x, y, paint); 1344ce59fca1cfad3489bc121e9b58a9c67e765ca35aAndy Huang } 1345ce59fca1cfad3489bc121e9b58a9c67e765ca35aAndy Huang 13460509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal /** 13470509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal * Set the background for this item based on: 13480509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal * 1. Read / Unread (unread messages have a lighter background) 13490509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal * 2. Tablet / Phone 13500509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal * 3. Checkbox checked / Unchecked (controls CAB color for item) 13510509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal * 4. Activated / Not activated (controls the blue highlight on tablet) 13520509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal */ 1353be0cb1e421831672f49c30ecb46e6eee765cb661Andrew Sapperstein private void updateBackground() { 13540509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal final int background; 1355103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy if (mBackgroundOverrideResId > 0) { 1356103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy background = mBackgroundOverrideResId; 13576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } else { 13586b57d9cedbe8f905d5845ef7ddebb2e1a053d3eeRohan Shah background = R.drawable.conversation_item_background; 13596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 13600509bba9a80de474a24368e1f3baebd3cd32cd5eVikram Aggarwal setBackgroundResource(background); 13616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira } 1362c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 13636126d72ae2769bd39451872f45781cadb5b90515Mark Wei @Override 1364ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao protected int[] onCreateDrawableState(int extraSpace) { 1365ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final int[] curr = super.onCreateDrawableState(extraSpace + 1); 1366ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mChecked) { 1367ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mergeDrawableStates(curr, CHECKED_STATE); 1368ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao } 1369ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao return curr; 1370ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao } 1371ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao 1372ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao private void setChecked(boolean checked) { 1373ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mChecked = checked; 1374ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao refreshDrawableState(); 1375ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao } 1376ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao 1377ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao @Override 1378ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public boolean toggleCheckedState() { 1379ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao return toggleCheckedState(null); 1380042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang } 1381042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 138212a05d22f6ac528e96716de9a451c5b7bee7a26dAndy Huang @Override 1383ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public boolean toggleCheckedState(final String sourceOpt) { 1384ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mHeader != null && mHeader.conversation != null && mCheckedConversationSet != null) { 1385ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao setChecked(!mChecked); 1386a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei final Conversation conv = mHeader.conversation; 1387bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp // Set the list position of this item in the conversation 1388a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei final SwipeableListView listView = getListView(); 1389a2640038ffe8a17fb435b0007ba4ca9ff14d00bdScott Kennedy 1390a2640038ffe8a17fb435b0007ba4ca9ff14d00bdScott Kennedy try { 1391f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao conv.position = mChecked && listView != null ? listView.getPositionForView(this) 1392f9b96e244e6c6a19cb1920ff129f424997db2727Jin Cao : Conversation.NO_POSITION; 1393a2640038ffe8a17fb435b0007ba4ca9ff14d00bdScott Kennedy } catch (final NullPointerException e) { 1394a2640038ffe8a17fb435b0007ba4ca9ff14d00bdScott Kennedy // TODO(skennedy) Remove this if we find the root cause b/9527863 1395a2640038ffe8a17fb435b0007ba4ca9ff14d00bdScott Kennedy } 1396042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 1397ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet.isEmpty()) { 1398042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang final String source = (sourceOpt != null) ? sourceOpt : "checkbox"; 1399042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang Analytics.getInstance().sendEvent("enter_cab_mode", source, null, 0); 1400bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp } 1401042a530b2296487fa5899a3e871214ac4a47e3d8Andy Huang 1402ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao mCheckedConversationSet.toggle(conv); 1403ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet.isEmpty()) { 140454f120f6ada40c7191811dfff99b151e9e192c78mindyp listView.commitDestructiveActions(true); 140554f120f6ada40c7191811dfff99b151e9e192c78mindyp } 14061fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy 1407ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao final boolean front = !mChecked; 1408a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView.flipTo(front); 14091fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy 1410bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp // We update the background after the checked state has changed 1411bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp // now that we have a selected background asset. Setting the background 1412bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp // usually waits for a layout pass, but we don't need a full layout, 1413bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp // just an update to the background. 1414bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp requestLayout(); 1415955a766f6c9c30e06dcd504ebc4dd6db510c2fa6Scott Kennedy 1416955a766f6c9c30e06dcd504ebc4dd6db510c2fa6Scott Kennedy return true; 1417bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp } 1418955a766f6c9c30e06dcd504ebc4dd6db510c2fa6Scott Kennedy 1419955a766f6c9c30e06dcd504ebc4dd6db510c2fa6Scott Kennedy return false; 1420bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp } 1421bad1a93d431bc599ed73fa4f42eeef313cd31626mindyp 1422a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei @Override 1423a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei public void onSetEmpty() { 1424a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei mSendersImageView.flipTo(true); 1425a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei } 1426a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 1427a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei @Override 1428ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public void onSetPopulated(final ConversationCheckedSet set) { } 1429a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 1430a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei @Override 1431ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao public void onSetChanged(final ConversationCheckedSet set) { } 1432a8301e2eb5a083a73f58331279c86e8ec7b11a48Mark Wei 1433c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira /** 1434c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira * Toggle the star on this view and update the conversation. 1435c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira */ 1436866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira public void toggleStar() { 14374f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira mHeader.conversation.starred = !mHeader.conversation.starred; 14384f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira Bitmap starBitmap = getStarBitmap(); 1439c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira postInvalidate(mCoordinates.starX, mCoordinates.starY, mCoordinates.starX 14404f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira + starBitmap.getWidth(), 14414f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira mCoordinates.starY + starBitmap.getHeight()); 1442bcdc0f995c05ec1842a74e853a87ae5048799d0cAlice Yang ConversationCursor cursor = (ConversationCursor) mAdapter.getCursor(); 1443bcdc0f995c05ec1842a74e853a87ae5048799d0cAlice Yang if (cursor != null) { 1444103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy // TODO(skennedy) What about ads? 14459e2d407fdafeb874e640eb84017feaf784309075Scott Kennedy cursor.updateBoolean(mHeader.conversation, ConversationColumns.STARRED, 1446bcdc0f995c05ec1842a74e853a87ae5048799d0cAlice Yang mHeader.conversation.starred); 1447bcdc0f995c05ec1842a74e853a87ae5048799d0cAlice Yang } 1448c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1449c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1450479505d71969e26b0785d8e0e1b81108731cf827Mark Wei private boolean isTouchInContactPhoto(float x, float y) { 1451a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // Everything before the end edge of contact photo 14529ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy 1453a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein final boolean isRtl = ViewUtils.isViewRtl(this); 1454a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein final int threshold = (isRtl) ? mCoordinates.contactImagesX - sSenderImageTouchSlop : 1455a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein mCoordinates.contactImagesX + mCoordinates.contactImagesWidth 14569ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy + sSenderImageTouchSlop; 14579ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy 14589ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy // Allow touching a little right of the contact photo when we're already in selection mode 14599ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy final float extra; 1460ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao if (mCheckedConversationSet == null || mCheckedConversationSet.isEmpty()) { 14619ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy extra = 0; 14629ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy } else { 14639ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy extra = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, 14649ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy getResources().getDisplayMetrics()); 14659ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy } 14669ba7fba9213027c6f763001d32d4c88f0d086388Scott Kennedy 1467479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return mHeader.gadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO 14680e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux && ((isRtl) ? x > (threshold - extra) : x < (threshold + extra)); 1469c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1470c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira 1471d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy private boolean isTouchInInfoIcon(final float x, final float y) { 1472d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mHeader.infoIcon == null) { 1473d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy // We have no info icon 1474d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy return false; 1475d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1476d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1477a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein final boolean isRtl = ViewUtils.isViewRtl(this); 1478a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein // Regardless of device, we always want to be end of the date's start touch slop 1479a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein if (((isRtl) ? x > mDateX + mDateWidth + sStarTouchSlop : x < mDateX - sStarTouchSlop)) { 1480d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy return false; 1481d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1482d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1483d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mStarEnabled) { 1484928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // We allow touches all the way to the right edge, so no x check is necessary 1485d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1486928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // We need to be above the star's touch area, which ends at the top of the subject 1487928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux // text 1488928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux return y < mCoordinates.subjectY; 1489d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1490d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1491d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy // With no star below the info icon, we allow touches anywhere from the top edge to the 14920e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux // bottom edge 14930e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux return true; 1494d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1495d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1496866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira private boolean isTouchInStar(float x, float y) { 1497928308d6b10d353493492ad05e0227f960ddaa7eJames Lemieux if (mHeader.infoIcon != null) { 1498d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy // We have an info icon, and it's above the star 1499d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy // We allow touches everywhere below the top of the subject text 1500d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (y < mCoordinates.subjectY) { 1501d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy return false; 1502d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1503d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1504d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy 1505c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Everything after the star and include a touch slop. 15060e29e769c74e385342fc5dc8e9c85517771aaa34James Lemieux return mStarEnabled && isTouchInStarTargetX(ViewUtils.isViewRtl(this), x); 1507479505d71969e26b0785d8e0e1b81108731cf827Mark Wei } 1508479505d71969e26b0785d8e0e1b81108731cf827Mark Wei 1509a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein private boolean isTouchInStarTargetX(boolean isRtl, float x) { 1510a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein return (isRtl) ? x < mCoordinates.starX + mCoordinates.starWidth + sStarTouchSlop 1511a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein : x >= mCoordinates.starX - sStarTouchSlop; 1512a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein } 1513a4296c179cd4eb12e7c4912d72c22dd2ec724a7eAndrew Sapperstein 1514304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blank @Override 1515a538984fcc19e7624f2650b119ede39bf1f35846mindyp public boolean canChildBeDismissed() { 1516512821c11d89d49908f3cfdee0b582601f500f3dJin Cao return mSwipeEnabled; 1517a538984fcc19e7624f2650b119ede39bf1f35846mindyp } 1518a538984fcc19e7624f2650b119ede39bf1f35846mindyp 1519a538984fcc19e7624f2650b119ede39bf1f35846mindyp @Override 1520a538984fcc19e7624f2650b119ede39bf1f35846mindyp public void dismiss() { 1521ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp SwipeableListView listView = getListView(); 15225254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (listView != null) { 1523e1ba1013409486f88f06af2932546a1b366704d3Jin Cao listView.dismissChild(this); 15245254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 15255bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira } 15265bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira 1527a4b9f78c174238045ec51a351553b39d876fb67emindyp private boolean onTouchEventNoSwipe(MotionEvent event) { 1528479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("on touch event no swipe"); 1529a4b9f78c174238045ec51a351553b39d876fb67emindyp boolean handled = false; 1530a4b9f78c174238045ec51a351553b39d876fb67emindyp 1531a4b9f78c174238045ec51a351553b39d876fb67emindyp int x = (int) event.getX(); 1532a4b9f78c174238045ec51a351553b39d876fb67emindyp int y = (int) event.getY(); 1533a4b9f78c174238045ec51a351553b39d876fb67emindyp switch (event.getAction()) { 1534a4b9f78c174238045ec51a351553b39d876fb67emindyp case MotionEvent.ACTION_DOWN: 1535d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (isTouchInContactPhoto(x, y) || isTouchInInfoIcon(x, y) || isTouchInStar(x, y)) { 1536a4b9f78c174238045ec51a351553b39d876fb67emindyp mDownEvent = true; 1537a4b9f78c174238045ec51a351553b39d876fb67emindyp handled = true; 1538a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1539a4b9f78c174238045ec51a351553b39d876fb67emindyp break; 1540a4b9f78c174238045ec51a351553b39d876fb67emindyp 1541a4b9f78c174238045ec51a351553b39d876fb67emindyp case MotionEvent.ACTION_CANCEL: 1542a4b9f78c174238045ec51a351553b39d876fb67emindyp mDownEvent = false; 1543a4b9f78c174238045ec51a351553b39d876fb67emindyp break; 1544a4b9f78c174238045ec51a351553b39d876fb67emindyp 1545a4b9f78c174238045ec51a351553b39d876fb67emindyp case MotionEvent.ACTION_UP: 1546a4b9f78c174238045ec51a351553b39d876fb67emindyp if (mDownEvent) { 1547479505d71969e26b0785d8e0e1b81108731cf827Mark Wei if (isTouchInContactPhoto(x, y)) { 1548a4b9f78c174238045ec51a351553b39d876fb67emindyp // Touch on the check mark 1549ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao toggleCheckedState(); 1550d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } else if (isTouchInInfoIcon(x, y)) { 1551d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mConversationItemAreaClickListener != null) { 1552d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mConversationItemAreaClickListener.onInfoIconClicked(); 1553d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1554a4b9f78c174238045ec51a351553b39d876fb67emindyp } else if (isTouchInStar(x, y)) { 15558afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy // Touch on the star 1556d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mConversationItemAreaClickListener == null) { 1557d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy toggleStar(); 1558d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } else { 1559d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mConversationItemAreaClickListener.onStarClicked(); 1560d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1561a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1562a4b9f78c174238045ec51a351553b39d876fb67emindyp handled = true; 1563a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1564a4b9f78c174238045ec51a351553b39d876fb67emindyp break; 1565a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1566a4b9f78c174238045ec51a351553b39d876fb67emindyp 1567a4b9f78c174238045ec51a351553b39d876fb67emindyp if (!handled) { 1568a4b9f78c174238045ec51a351553b39d876fb67emindyp handled = super.onTouchEvent(event); 1569a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1570a4b9f78c174238045ec51a351553b39d876fb67emindyp 1571479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1572a4b9f78c174238045ec51a351553b39d876fb67emindyp return handled; 1573a4b9f78c174238045ec51a351553b39d876fb67emindyp } 1574a4b9f78c174238045ec51a351553b39d876fb67emindyp 1575b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira /** 1576866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * ConversationItemView is given the first chance to handle touch events. 1577866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1578c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira @Override 1579c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira public boolean onTouchEvent(MotionEvent event) { 1580479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("on touch event"); 15811e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira int x = (int) event.getX(); 15821e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira int y = (int) event.getY(); 1583f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira if (!mSwipeEnabled) { 1584479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1585f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira return onTouchEventNoSwipe(event); 1586f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira } 1587c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira switch (event.getAction()) { 1588c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira case MotionEvent.ACTION_DOWN: 1589d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (isTouchInContactPhoto(x, y) || isTouchInInfoIcon(x, y) || isTouchInStar(x, y)) { 1590960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira mDownEvent = true; 1591479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1592960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1593960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1594c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira break; 1595c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira case MotionEvent.ACTION_UP: 1596c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira if (mDownEvent) { 1597479505d71969e26b0785d8e0e1b81108731cf827Mark Wei if (isTouchInContactPhoto(x, y)) { 1598c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira // Touch on the check mark 1599479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1600960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira mDownEvent = false; 1601ec0fa48764bede0772e9c711f3e33361b62f3608Jin Cao toggleCheckedState(); 1602479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1603960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1604d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } else if (isTouchInInfoIcon(x, y)) { 1605d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy // Touch on the info icon 1606d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mDownEvent = false; 1607d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mConversationItemAreaClickListener != null) { 1608d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mConversationItemAreaClickListener.onInfoIconClicked(); 1609d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1610d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy Utils.traceEndSection(); 1611d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy return true; 1612866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } else if (isTouchInStar(x, y)) { 16138afccad8b03701577bb4b734a0f4fe76f6cab487Scott Kennedy // Touch on the star 1614d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mDownEvent = false; 1615d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy if (mConversationItemAreaClickListener == null) { 1616d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy toggleStar(); 1617d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } else { 1618d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy mConversationItemAreaClickListener.onStarClicked(); 1619d35dcd8d74d2cc95ccaf28a5bc28344fda309fc3Scott Kennedy } 1620479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1621479505d71969e26b0785d8e0e1b81108731cf827Mark Wei return true; 1622c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1623c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1624c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira break; 1625c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1626ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal // Let View try to handle it as well. 1627960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira boolean handled = super.onTouchEvent(event); 1628960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira if (event.getAction() == MotionEvent.ACTION_DOWN) { 1629479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1630960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return true; 1631960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1632479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1633960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return handled; 1634c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira } 1635866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1636960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira @Override 1637960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira public boolean performClick() { 1638f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal final boolean handled = super.performClick(); 1639f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal final SwipeableListView list = getListView(); 1640103319aaed26bce257de55b2fe93d4f78d3c59b9Scott Kennedy if (!handled && list != null && list.getAdapter() != null) { 1641f69d0394f7de5c0681b8d5d5ca0c60b55c55f815Vikram Aggarwal final int pos = list.findConversation(this, mHeader.conversation); 1642960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira list.performItemClick(this, pos, mHeader.conversation.id); 1643960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira } 1644960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira return handled; 16451e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira } 16461e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira 1647e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy private View unwrap() { 164879c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang final ViewParent vp = getParent(); 1649e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy if (vp == null || !(vp instanceof View)) { 165079c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang return null; 165179c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 1652e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy return (View) vp; 165379c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 165479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang 1655a538984fcc19e7624f2650b119ede39bf1f35846mindyp private SwipeableListView getListView() { 165679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang SwipeableListView v = null; 1657e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy final View wrapper = unwrap(); 1658e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy if (wrapper != null && wrapper instanceof SwipeableConversationItemView) { 1659e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy v = (SwipeableListView) ((SwipeableConversationItemView) wrapper).getListView(); 166079c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang } 16615254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp if (v == null) { 16625254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp v = mAdapter.getListView(); 16635254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp } 16645254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp return v; 16651ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira } 16661ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira 1667866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira /** 16685c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira * Reset any state associated with this conversation item view so that it 16695c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira * can be reused. 16705c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira */ 16715c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira public void reset() { 1672479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceBeginSection("reset"); 1673370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang setAlpha(1f); 1674370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang setTranslationX(0f); 1675370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mAnimatedHeightFraction = 1.0f; 1676479505d71969e26b0785d8e0e1b81108731cf827Mark Wei Utils.traceEndSection(); 1677370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 1678370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 1679370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @SuppressWarnings("deprecation") 1680370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang @Override 1681370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void setTranslationX(float translationX) { 1682370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang super.setTranslationX(translationX); 1683370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 168479c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang // When a list item is being swiped or animated, ensure that the hosting view has a 168579c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang // background color set. We only enable the background during the X-translation effect to 168679c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang // reduce overdraw during normal list scrolling. 1687e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy final View parent = (View) getParent(); 168879c3e1ed9cb1e1660c5d34b7bf3f3ab5c5dd5162Andy Huang if (parent == null) { 1689e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy LogUtils.w(LOG_TAG, "CIV.setTranslationX null ConversationItemView parent x=%s", 1690e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy translationX); 1691370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 1692370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang 1693e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy if (parent instanceof SwipeableConversationItemView) { 1694e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy if (translationX != 0f) { 1695e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy parent.setBackgroundResource(R.color.swiped_bg_color); 1696e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy } else { 1697e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy parent.setBackgroundDrawable(null); 1698e5707f86f340797d5ee1535bff86d331715cbce9Scott Kennedy } 1699370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang } 17005c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira } 17015c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira 17025c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira /** 1703866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1704866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira * back from a destructive action. 1705866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira */ 1706370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public Animator createSwipeUndoAnimation() { 1707067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator undoAnimator = createTranslateXAnimation(true); 1708370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang return undoAnimator; 1709866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira } 1710866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira 1711bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira /** 1712bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1713bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira * back from a destructive action. 1714bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira */ 1715370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public Animator createUndoAnimation() { 1716067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator height = createHeightAnimation(true); 1717370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang Animator fade = ObjectAnimator.ofFloat(this, "alpha", 0, 1.0f); 1718067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira fade.setDuration(sShrinkAnimationDuration); 1719067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira fade.setInterpolator(new DecelerateInterpolator(2.0f)); 1720067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira AnimatorSet transitionSet = new AnimatorSet(); 1721067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.playTogether(height, fade); 1722370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang transitionSet.addListener(new HardwareLayerEnabler(this)); 1723370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang return transitionSet; 1724067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1725067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 1726067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira /** 1727067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * Grow the height of the item and fade it in when bringing a conversation 1728067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira * back from a destructive action. 1729067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira */ 1730370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public Animator createDestroyWithSwipeAnimation() { 1731067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator slide = createTranslateXAnimation(false); 1732067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator height = createHeightAnimation(false); 1733bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira AnimatorSet transitionSet = new AnimatorSet(); 1734067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira transitionSet.playSequentially(slide, height); 1735370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang return transitionSet; 1736bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1737bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 1738067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private ObjectAnimator createTranslateXAnimation(boolean show) { 1739ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp SwipeableListView parent = getListView(); 1740ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp // If we can't get the parent...we have bigger problems. 1741ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp int width = parent != null ? parent.getMeasuredWidth() : 0; 1742ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp final float start = show ? width : 0f; 1743ffd39aa99f185385941595c1da7e09c2a4a4c146mindyp final float end = show ? 0f : width; 1744067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira ObjectAnimator slide = ObjectAnimator.ofFloat(this, "translationX", start, end); 1745067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira slide.setInterpolator(new DecelerateInterpolator(2.0f)); 1746067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira slide.setDuration(sSlideAnimationDuration); 1747067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return slide; 1748067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1749067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 1750370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public Animator createDestroyAnimation() { 1751370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang return createHeightAnimation(false); 17525c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira } 17535c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira 1754067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira private ObjectAnimator createHeightAnimation(boolean show) { 1755370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final float start = show ? 0f : 1.0f; 1756370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang final float end = show ? 1.0f : 0f; 1757370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang ObjectAnimator height = ObjectAnimator.ofFloat(this, "animatedHeightFraction", start, end); 1758067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira height.setInterpolator(new DecelerateInterpolator(2.0f)); 1759067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira height.setDuration(sShrinkAnimationDuration); 1760067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira return height; 1761067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira } 1762067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira 1763bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira // Used by animator 1764370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang public void setAnimatedHeightFraction(float height) { 1765370f868c834861e7732faaa9bdd07a0fa0105596Andy Huang mAnimatedHeightFraction = height; 1766bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira requestLayout(); 1767bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira } 1768bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira 1769350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira @Override 17702102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei public SwipeableView getSwipeableView() { 17712102b2c87a6cb39bc63fb7eff13dda64da56b72eMark Wei return SwipeableView.from(this); 17726c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira } 17735390fcabb7baf683fc14bd68d8612913dac70a81mindyp 1774d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp @Override 1775d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp public float getMinAllowScrollDistance() { 1776d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp return sScrollSlop; 1777d064972c4a032f3c5cfcb236aa470273f7ac2ce0mindyp } 17781fea6a3cffcc8c4afc3d877e5dc57d29f9665942Scott Kennedy 17793dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao public String getAccountEmailAddress() { 17803dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao return mAccount.getEmailAddress(); 1781022aeeffe491ed8c3deeaf7c0fc7570d57af12bbScott Kennedy } 1782bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook} 1783