ConversationItemView.java revision 850c55ee2cab6b1c224366c66502f5d5f55018eb
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;
21304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport android.animation.Animator.AnimatorListener;
22bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereiraimport android.animation.AnimatorSet;
23866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.animation.ObjectAnimator;
24304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport android.content.Context;
256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.content.res.Resources;
26f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereiraimport android.database.Cursor;
276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Bitmap;
286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.BitmapFactory;
296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Canvas;
306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Color;
31b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.LinearGradient;
32b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.Paint;
336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Rect;
34b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport android.graphics.Shader;
356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.Typeface;
366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.graphics.drawable.Drawable;
376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Layout.Alignment;
386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.Spannable;
39b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereiraimport android.text.SpannableString;
406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.SpannableStringBuilder;
416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.StaticLayout;
426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextPaint;
436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils;
446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.TextUtils.TruncateAt;
456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.format.DateUtils;
466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.CharacterStyle;
476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.ForegroundColorSpan;
486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.text.style.StyleSpan;
496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.util.SparseArray;
50850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.Gravity;
516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.MotionEvent;
526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereiraimport android.view.View;
53850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.ViewGroup;
54850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.view.ViewGroup.LayoutParams;
55866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport android.view.animation.DecelerateInterpolator;
56f892f0a57d5c24b09fdc805f0fe2007ecd0d0e91Marc Blankimport android.widget.ListView;
57850c55ee2cab6b1c224366c66502f5d5f55018ebmindypimport android.widget.TextView;
586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
59732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.R;
60732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.browse.ConversationItemViewModel.SenderFragment;
61732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.perf.Timer;
62732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.providers.Conversation;
63b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.providers.Folder;
643cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereiraimport com.android.mail.providers.UIProvider;
65c8a994227b9c686d88ee05840544162711a85712Marc Blankimport com.android.mail.providers.UIProvider.ConversationColumns;
66bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.ui.AnimatedAdapter;
67e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereiraimport com.android.mail.ui.ControllableActivity;
681ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.ui.ConversationSelectionSet;
69b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereiraimport com.android.mail.ui.FolderDisplayer;
706c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereiraimport com.android.mail.ui.SwipeableItemView;
71a538984fcc19e7624f2650b119ede39bf1f35846mindypimport com.android.mail.ui.SwipeableListView;
721ddcf0f2bf44d3c9db89112ef52510d9b2433ac4Vikram Aggarwalimport com.android.mail.ui.ViewMode;
732f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwalimport com.android.mail.utils.LogTag;
74732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huangimport com.android.mail.utils.Utils;
75304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blankimport com.google.common.annotations.VisibleForTesting;
76732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
776c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereirapublic class ConversationItemView extends View implements SwipeableItemView {
786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Timer.
796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static int sLayoutCount = 0;
80bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook    private static Timer sTimer; // Create the sTimer here if you need to do
81bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                                 // perf analysis.
826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static final int PERF_LAYOUT_ITERATIONS = 50;
836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static final String PERF_TAG_LAYOUT = "CCHV.layout";
846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static final String PERF_TAG_CALCULATE_TEXTS_BITMAPS = "CCHV.txtsbmps";
856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static final String PERF_TAG_CALCULATE_SENDER_SUBJECT = "CCHV.sendersubj";
8630fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira    private static final String PERF_TAG_CALCULATE_FOLDERS = "CCHV.folders";
876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static final String PERF_TAG_CALCULATE_COORDINATES = "CCHV.coordinates";
882f1f62ace49a6596e9f1eee78acfd607bbb4de87Vikram Aggarwal    private static final String LOG_TAG = LogTag.getLogTag();
896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Static bitmaps.
916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap CHECKMARK_OFF;
926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap CHECKMARK_ON;
936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap STAR_OFF;
946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap STAR_ON;
956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap ATTACHMENT;
966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap ONLY_TO_ME;
976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap TO_ME_AND_OTHERS;
986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap IMPORTANT_ONLY_TO_ME;
996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap IMPORTANT_TO_ME_AND_OTHERS;
1006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap IMPORTANT_TO_OTHERS;
1016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static Bitmap DATE_BACKGROUND;
10254467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira    private static Bitmap STATE_REPLIED;
10354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira    private static Bitmap STATE_FORWARDED;
10454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira    private static Bitmap STATE_REPLIED_AND_FORWARDED;
1058d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira    private static Bitmap STATE_CALENDAR_INVITE;
1066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
107ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static String sSendersSplitToken;
108ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static String sElidedPaddingToken;
10984cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira    private static String sEllipsis;
11024538e893ef2db41a4c1b341f676b64422920304Mindy Pereira
1116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Static colors.
112ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sDefaultTextColor;
113ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sActivatedTextColor;
114ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSubjectTextColorRead;
115ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSubjectTextColorUnead;
116ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSnippetTextColorRead;
117ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSnippetTextColorUnread;
118ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSendersTextColorRead;
119ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sSendersTextColorUnread;
120ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sDateTextColor;
121ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sDateBackgroundPaddingLeft;
122ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private static int sTouchSlop;
1236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static int sDateBackgroundHeight;
1246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static int sStandardScaledDimen;
125067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    private static int sShrinkAnimationDuration;
126067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    private static int sSlideAnimationDuration;
127d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira    private static int sAnimatingBackgroundColor;
1286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Static paints.
1306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static TextPaint sPaint = new TextPaint();
13130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira    private static TextPaint sFoldersPaint = new TextPaint();
1326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Backgrounds for different states.
1346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>();
1356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    // Dimensions and coordinates.
1376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int mViewWidth = -1;
1386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int mMode = -1;
1396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int mDateX;
1406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int mPaperclipX;
14130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira    private int mFoldersXEnd;
1426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int mSendersWidth;
1436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    /** Whether we're running under test mode. */
1456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private boolean mTesting = false;
146fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal    /** Whether we are on a tablet device or not */
147fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal    private final boolean mTabletDevice;
1486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    @VisibleForTesting
1500944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira    ConversationItemViewCoordinates mCoordinates;
1516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private final Context mContext;
1536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
154866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public ConversationItemViewModel mHeader;
155c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    private boolean mDownEvent;
156d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal    private boolean mChecked = false;
1576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static int sFadedActivatedColor = -1;
15811b0bbdf024ec1413f90b2baac2c18a8f1c01d71Mindy Pereira    private ConversationSelectionSet mSelectedConversationSet;
1594584a0d83e160444f931cb565185a2eea39b1683Mindy Pereira    private Folder mDisplayedFolder;
1603cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira    private boolean mPriorityMarkersEnabled;
161b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira    private boolean mCheckboxesEnabled;
162f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    private boolean mSwipeEnabled;
163bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook    private AnimatedAdapter mAdapter;
164bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    private int mAnimatedHeight = -1;
165c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira    private String mAccount;
166e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira    private ControllableActivity mActivity;
1678a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    private CharacterStyle mActivatedTextSpan;
1685c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    private int mBackgroundOverride = -1;
169850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp    private static int sSendersTextViewTopPadding;
170850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp    private static int sSendersTextViewHeight;
1718a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    private static ForegroundColorSpan sActivatedTextSpan;
172fb7bace9a83abf0e8726def19e76cb03afdf5740Mindy Pereira    private static Bitmap sDateBackgroundAttachment;
173fb7bace9a83abf0e8726def19e76cb03afdf5740Mindy Pereira    private static Bitmap sDateBackgroundNoAttachment;
174350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira    private static int sUndoAnimationOffset;
175b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira    private static Bitmap MORE_FOLDERS;
1766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    static {
1786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setAntiAlias(true);
17930fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira        sFoldersPaint.setAntiAlias(true);
1806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
1816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
182b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira    /**
183b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira     * Handles displaying folders in a conversation header view.
184b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira     */
185b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira    static class ConversationItemFolderDisplayer extends FolderDisplayer {
186b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        // Maximum number of folders to be displayed.
187b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        private static final int MAX_DISPLAYED_FOLDERS_COUNT = 4;
188b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
189b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        private int mFoldersCount;
190b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        private boolean mHasMoreFolders;
191b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
192c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang        public ConversationItemFolderDisplayer(Context context) {
193c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang            super(context);
194c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang        }
195c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang
196b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        @Override
19785c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira        public void loadConversationFolders(Conversation conv, Folder ignoreFolder) {
19885c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira            super.loadConversationFolders(conv, ignoreFolder);
199b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
200c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang            mFoldersCount = mFoldersSortedSet.size();
201b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            mHasMoreFolders = mFoldersCount > MAX_DISPLAYED_FOLDERS_COUNT;
202b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            mFoldersCount = Math.min(mFoldersCount, MAX_DISPLAYED_FOLDERS_COUNT);
203b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
204b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
205b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        public boolean hasVisibleFolders() {
206b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            return mFoldersCount > 0;
207b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
208b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
209b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        private int measureFolders(int mode) {
210b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int availableSpace = ConversationItemViewCoordinates.getFoldersWidth(mContext, mode);
211b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int cellSize = ConversationItemViewCoordinates.getFolderCellWidth(mContext, mode,
212b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    mFoldersCount);
213b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
214b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int totalWidth = 0;
215c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang            for (Folder f : mFoldersSortedSet) {
216c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                final String folderString = f.name;
217c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                int width = (int) sFoldersPaint.measureText(folderString) + cellSize;
218b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (width % cellSize != 0) {
219b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    width += cellSize - (width % cellSize);
220b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
221b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                totalWidth += width;
222b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (totalWidth > availableSpace) {
223b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    break;
224b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
225b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            }
226b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
227b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            return totalWidth;
228b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
229b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
230b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        public void drawFolders(Canvas canvas, ConversationItemViewCoordinates coordinates,
231b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                int foldersXEnd, int mode) {
232b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            if (mFoldersCount == 0) {
233b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                return;
234b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            }
235b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
236b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int xEnd = foldersXEnd;
237b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int y = coordinates.foldersY - coordinates.foldersAscent;
238b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int height = coordinates.foldersHeight;
239b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int topPadding = coordinates.foldersTopPadding;
240b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int ascent = coordinates.foldersAscent;
241b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            sFoldersPaint.setTextSize(coordinates.foldersFontSize);
242b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
243b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            // Initialize space and cell size based on the current mode.
244b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int availableSpace = ConversationItemViewCoordinates.getFoldersWidth(mContext, mode);
245b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int averageWidth = availableSpace / mFoldersCount;
246b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int cellSize = ConversationItemViewCoordinates.getFolderCellWidth(mContext, mode,
247b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    mFoldersCount);
248b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
249b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            // First pass to calculate the starting point.
250b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int totalWidth = measureFolders(mode);
251b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            int xStart = xEnd - Math.min(availableSpace, totalWidth);
252b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
253b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            // Second pass to draw folders.
254c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang            for (Folder f : mFoldersSortedSet) {
255c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                final String folderString = f.name;
256c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                final int fgColor = f.getForegroundColor(mDefaultFgColor);
257c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                final int bgColor = f.getBackgroundColor(mDefaultBgColor);
258b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                int width = cellSize;
259b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                boolean labelTooLong = false;
260c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                width = (int) sFoldersPaint.measureText(folderString) + cellSize;
261b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (width % cellSize != 0) {
262b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    width += cellSize - (width % cellSize);
263b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
264b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (totalWidth > availableSpace && width > averageWidth) {
265b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    width = averageWidth;
266a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    labelTooLong = true;
267b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
268b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
269b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                // TODO (mindyp): how to we get this?
270b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                final boolean isMuted = false;
271bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                // labelValues.folderId ==
272bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                // sGmail.getFolderMap(mAccount).getFolderIdIgnored();
273b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
274b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                // Draw the box.
275c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                sFoldersPaint.setColor(bgColor);
276b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                sFoldersPaint.setStyle(isMuted ? Paint.Style.STROKE : Paint.Style.FILL_AND_STROKE);
277b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                canvas.drawRect(xStart, y + ascent, xStart + width, y + ascent + height,
278b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                        sFoldersPaint);
279b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
280b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                // Draw the text.
281c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang                int padding = getPadding(width, (int) sFoldersPaint.measureText(folderString));
282b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (labelTooLong) {
283a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    TextPaint shortPaint = new TextPaint();
284a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    shortPaint.setColor(fgColor);
285a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    shortPaint.setTextSize(coordinates.foldersFontSize);
286b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    padding = cellSize / 2;
287b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    int rightBorder = xStart + width - padding;
288b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    Shader shader = new LinearGradient(rightBorder - padding, y, rightBorder, y,
289a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                            fgColor, Utils.getTransparentColor(fgColor), Shader.TileMode.CLAMP);
290a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    shortPaint.setShader(shader);
291a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    canvas.drawText(folderString, xStart + padding, y + topPadding, shortPaint);
292a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                } else {
293a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    sFoldersPaint.setColor(fgColor);
294a293987a6bc4d0b1089db95555abc9ac32939882Mindy Pereira                    canvas.drawText(folderString, xStart + padding, y + topPadding, sFoldersPaint);
295b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
296b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
297b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                availableSpace -= width;
298b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                xStart += width;
299b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (availableSpace <= 0 && mHasMoreFolders) {
300b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    canvas.drawBitmap(MORE_FOLDERS, xEnd, y + ascent, sFoldersPaint);
301b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    return;
302b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
303b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            }
304b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
305acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    }
306b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
307acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    /**
308acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira     * Helpers function to align an element in the center of a space.
309acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira     */
310acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    private static int getPadding(int space, int length) {
311acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira        return (space - length) / 2;
312b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira    }
313b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
3140944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira    public ConversationItemView(Context context, String account) {
3156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        super(context);
316960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        setClickable(true);
317960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        setLongClickable(true);
3186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mContext = context.getApplicationContext();
319fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal        mTabletDevice = Utils.useTabletUI(mContext);
320c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira        mAccount = account;
3216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        Resources res = mContext.getResources();
3226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
3236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (CHECKMARK_OFF == null) {
3246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // Initialize static bitmaps.
3256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            CHECKMARK_OFF = BitmapFactory.decodeResource(res,
3266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.btn_check_off_normal_holo_light);
3276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            CHECKMARK_ON = BitmapFactory.decodeResource(res,
3286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.btn_check_on_normal_holo_light);
3296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            STAR_OFF = BitmapFactory.decodeResource(res,
3306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.btn_star_off_normal_email_holo_light);
3316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            STAR_ON = BitmapFactory.decodeResource(res,
3326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.btn_star_on_normal_email_holo_light);
3336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            ONLY_TO_ME = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_double);
3346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_single);
3356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            IMPORTANT_ONLY_TO_ME = BitmapFactory.decodeResource(res,
3366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.ic_email_caret_double_important_unread);
3376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            IMPORTANT_TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res,
3386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.ic_email_caret_single_important_unread);
3396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            IMPORTANT_TO_OTHERS = BitmapFactory.decodeResource(res,
3406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    R.drawable.ic_email_caret_none_important_unread);
3416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attachment_holo_light);
342b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            MORE_FOLDERS = BitmapFactory.decodeResource(res, R.drawable.ic_folders_more);
343e9a81035bcef5a372fa13a992f8553eb60e6aaf0Vikram Aggarwal            DATE_BACKGROUND = BitmapFactory.decodeResource(res, R.drawable.folder_bg_holo_light);
34454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            STATE_REPLIED =
34554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                    BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_holo_light);
34654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            STATE_FORWARDED =
34754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                    BitmapFactory.decodeResource(res, R.drawable.ic_badge_forward_holo_light);
34854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            STATE_REPLIED_AND_FORWARDED =
34954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                    BitmapFactory.decodeResource(res, R.drawable.ic_badge_reply_forward_holo_light);
3508d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira            STATE_CALENDAR_INVITE =
3518d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira                    BitmapFactory.decodeResource(res, R.drawable.ic_badge_invite_holo_light);
3526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
3536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // Initialize colors.
354ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sDefaultTextColor = res.getColor(R.color.default_text_color);
355ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sActivatedTextColor = res.getColor(android.R.color.white);
3568a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            sActivatedTextSpan = new ForegroundColorSpan(sActivatedTextColor);
357ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSubjectTextColorRead = res.getColor(R.color.subject_text_color_read);
358ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSubjectTextColorUnead = res.getColor(R.color.subject_text_color_unread);
359ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSnippetTextColorRead = res.getColor(R.color.snippet_text_color_read);
360ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSnippetTextColorUnread = res.getColor(R.color.snippet_text_color_unread);
361ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSendersTextColorRead = res.getColor(R.color.senders_text_color_read);
362ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSendersTextColorUnread = res.getColor(R.color.senders_text_color_unread);
363ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sDateTextColor = res.getColor(R.color.date_text_color);
364ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sDateBackgroundPaddingLeft = res
3656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    .getDimensionPixelSize(R.dimen.date_background_padding_left);
366ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sTouchSlop = res.getDimensionPixelSize(R.dimen.touch_slop);
3676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height);
3686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sStandardScaledDimen = res.getDimensionPixelSize(R.dimen.standard_scaled_dimen);
369067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            sShrinkAnimationDuration = res.getInteger(R.integer.shrink_animation_duration);
370067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira            sSlideAnimationDuration = res.getInteger(R.integer.slide_animation_duration);
371350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            sUndoAnimationOffset = res.getDimensionPixelOffset(R.dimen.undo_animation_offset);
3726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // Initialize static color.
373ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sSendersSplitToken = res.getString(R.string.senders_split_token);
374ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sElidedPaddingToken = res.getString(R.string.elided_padding_token);
37584cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira            sEllipsis = res.getString(R.string.ellipsis);
376d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira            sAnimatingBackgroundColor = res.getColor(R.color.animating_item_background_color);
377850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            sSendersTextViewTopPadding = res.getDimensionPixelSize
378850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                    (R.dimen.senders_textview_top_padding);
379850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            sSendersTextViewHeight = res.getDimensionPixelSize
380850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                    (R.dimen.senders_textview_height);
3816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
3826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
3836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
384e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira    public void bind(Cursor cursor, ControllableActivity activity, ConversationSelectionSet set,
385e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira            Folder folder, boolean checkboxesDisabled, boolean swipeEnabled,
386e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira            boolean priorityArrowEnabled, AnimatedAdapter adapter) {
387e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira        bind(ConversationItemViewModel.forCursor(mAccount, cursor), activity, set, folder,
38833519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal                checkboxesDisabled, swipeEnabled, priorityArrowEnabled, adapter);
389b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira    }
390b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira
391e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira    public void bind(Conversation conversation, ControllableActivity activity,
392e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira            ConversationSelectionSet set, Folder folder, boolean checkboxesDisabled,
393e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira            boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
394e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira        bind(ConversationItemViewModel.forConversation(mAccount, conversation), activity, set,
39533519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal                folder, checkboxesDisabled, swipeEnabled, priorityArrowEnabled, adapter);
396acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira    }
397acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira
398e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira    private void bind(ConversationItemViewModel header, ControllableActivity activity,
399acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira            ConversationSelectionSet set, Folder folder, boolean checkboxesDisabled,
40033519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal            boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
401acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira        mHeader = header;
402e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira        mActivity = activity;
403b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira        mSelectedConversationSet = set;
404b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira        mDisplayedFolder = folder;
40590fc0ffa0ad4fcde94fa9648df7f8041bfb6a943Mindy Pereira        mCheckboxesEnabled = !checkboxesDisabled;
406f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        mSwipeEnabled = swipeEnabled;
40733519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal        mPriorityMarkersEnabled = priorityArrowEnabled;
408bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook        mAdapter = adapter;
409f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira        setContentDescription(mHeader.getContentDescription(mContext));
410f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira        requestLayout();
411f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira    }
412f9573c5f07bcc05409b5d4c15772884c5313c407Mindy Pereira
413866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    /**
414866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * Get the Conversation object associated with this view.
415866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     */
416732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    public Conversation getConversation() {
417732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        return mHeader.conversation;
418732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang    }
419732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang
4206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    /**
4216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     * Sets the mode. Only used for testing.
4226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     */
4236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    @VisibleForTesting
4246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    void setMode(int mode) {
4256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mMode = mode;
4266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mTesting = true;
4276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
4286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static void startTimer(String tag) {
4306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (sTimer != null) {
4316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sTimer.start(tag);
4326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
4346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private static void pauseTimer(String tag) {
4366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (sTimer != null) {
4376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sTimer.pause(tag);
4386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
4406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    @Override
4426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
4436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        startTimer(PERF_TAG_LAYOUT);
4446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        super.onLayout(changed, left, top, right, bottom);
4466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        int width = right - left;
4486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (width != mViewWidth) {
4496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mViewWidth = width;
4506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (!mTesting) {
451e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira                mMode = ConversationItemViewCoordinates.getMode(mContext, mActivity.getViewMode());
4526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
4536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mHeader.viewWidth = mViewWidth;
4556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        Resources res = getResources();
4566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen);
4576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.standardScaledDimen != sStandardScaledDimen) {
4586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // Large Text has been toggle on/off. Update the static dimens.
4596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sStandardScaledDimen = mHeader.standardScaledDimen;
4600944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira            ConversationItemViewCoordinates.refreshConversationHeights(mContext);
4616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sDateBackgroundHeight = res.getDimensionPixelSize(R.dimen.date_background_height);
4626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4630944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira        mCoordinates = ConversationItemViewCoordinates.forWidth(mContext, mViewWidth, mMode,
4646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                mHeader.standardScaledDimen);
4656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        calculateTextsAndBitmaps();
4666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        calculateCoordinates();
4676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mHeader.validate(mContext);
4686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        pauseTimer(PERF_TAG_LAYOUT);
4706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (sTimer != null && ++sLayoutCount >= PERF_LAYOUT_ITERATIONS) {
4716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sTimer.dumpResults();
4726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sTimer = new Timer();
4736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            sLayoutCount = 0;
4746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
4766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    @Override
4786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    public void setBackgroundResource(int resourceId) {
4796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        Drawable drawable = mBackgrounds.get(resourceId);
4806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (drawable == null) {
4816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            drawable = getResources().getDrawable(resourceId);
4826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mBackgrounds.put(resourceId, drawable);
4836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (getBackground() != drawable) {
4856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            super.setBackgroundDrawable(drawable);
4866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
4876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
4886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
4896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private void calculateTextsAndBitmaps() {
4906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        startTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
491d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal        if (mSelectedConversationSet != null) {
492d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal            mChecked = mSelectedConversationSet.contains(mHeader.conversation);
493d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal        }
4946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Update font color.
495ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        int fontColor = getFontColor(sDefaultTextColor);
4966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        boolean fontChanged = false;
4976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.fontColor != fontColor) {
4986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            fontChanged = true;
4996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mHeader.fontColor = fontColor;
5006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
5016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5028d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        boolean isUnread = mHeader.unread;
5036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
504b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira        final boolean checkboxEnabled = mCheckboxesEnabled;
5056f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.checkboxVisible != checkboxEnabled) {
5066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mHeader.checkboxVisible = checkboxEnabled;
5076f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
5086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5096f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Update background.
5106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        updateBackground(isUnread);
5116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.isLayoutValid(mContext)) {
5136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // Relayout subject if font color has changed.
5146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (fontChanged) {
5150b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                layoutSubjectSpans(isUnread);
5166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                layoutSubject();
5178a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira                layoutSenderSpans();
5186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
5196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
5206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            return;
5216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
5226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
52330fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira        startTimer(PERF_TAG_CALCULATE_FOLDERS);
524b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
525b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        // Initialize folder displayer.
526b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        if (mCoordinates.showFolders) {
527c03208720e5650f0acb748f82ed10ac770d6ceb4Andy Huang            mHeader.folderDisplayer = new ConversationItemFolderDisplayer(mContext);
52885c4a77abd849f5f3f0236d51554bb1bb99fe8f6Mindy Pereira            mHeader.folderDisplayer.loadConversationFolders(mHeader.conversation, mDisplayedFolder);
529b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
530b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
53130fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira        pauseTimer(PERF_TAG_CALCULATE_FOLDERS);
5326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
533732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        mHeader.dateText = DateUtils.getRelativeTimeSpanString(mContext,
534732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang                mHeader.conversation.dateMs).toString();
5356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Paper clip icon.
5376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mHeader.paperclip = null;
538732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        if (mHeader.conversation.hasAttachments) {
5396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mHeader.paperclip = ATTACHMENT;
5406f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
5416f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Personal level.
5426f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mHeader.personalLevelBitmap = null;
5433cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira        if (mCoordinates.showPersonalLevel) {
544583eea0562dff158bdd3db9c2adfaec9b7ebef68Mindy Pereira            final int personalLevel = mHeader.conversation.personalLevel;
5453cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira            final boolean isImportant =
546583eea0562dff158bdd3db9c2adfaec9b7ebef68Mindy Pereira                    mHeader.conversation.priority == UIProvider.ConversationPriority.IMPORTANT;
54733519c002b7e4504dbf964a808cf2f7aff32d16cVikram Aggarwal            final boolean useImportantMarkers = isImportant && mPriorityMarkersEnabled;
5483cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira
5493cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira            if (personalLevel == UIProvider.ConversationPersonalLevel.ONLY_TO_ME) {
5503cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira                mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_ONLY_TO_ME
5513cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira                        : ONLY_TO_ME;
5523cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira            } else if (personalLevel == UIProvider.ConversationPersonalLevel.TO_ME_AND_OTHERS) {
5533cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira                mHeader.personalLevelBitmap = useImportantMarkers ? IMPORTANT_TO_ME_AND_OTHERS
5543cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira                        : TO_ME_AND_OTHERS;
5553cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira            } else if (useImportantMarkers) {
5563cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira                mHeader.personalLevelBitmap = IMPORTANT_TO_OTHERS;
5573cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira            }
5583cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira        }
5596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        startTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT);
5616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Subject.
5630b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        layoutSubjectSpans(isUnread);
5646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
565d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang        mHeader.sendersDisplayText = new SpannableStringBuilder();
5666c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira        mHeader.styledSendersString = new SpannableStringBuilder();
567d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang
5686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Parse senders fragments.
569c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira        if (mHeader.conversation.conversationInfo != null) {
570b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            Context context = getContext();
571b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira            mHeader.messageInfoString = SendersView
572b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira                    .createMessageInfo(context, mHeader.conversation);
573b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            int maxChars = ConversationItemViewCoordinates.getSubjectLength(context,
574e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira                    ConversationItemViewCoordinates.getMode(context, mActivity.getViewMode()),
575b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                    mHeader.folderDisplayer != null && mHeader.folderDisplayer.mFoldersCount > 0,
576b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                    mHeader.conversation.hasAttachments);
577b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            mHeader.styledSenders = SendersView.format(context,
578b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                    mHeader.conversation.conversationInfo, mHeader.messageInfoString.toString(),
579b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                    maxChars);
580c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira        } else {
58177d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira            SendersView.formatSenders(mHeader, getContext());
582c3efca18f09904f4ce39395169559c5d82bd3d06Mindy Pereira        }
5836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        pauseTimer(PERF_TAG_CALCULATE_SENDER_SUBJECT);
5856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        pauseTimer(PERF_TAG_CALCULATE_TEXTS_BITMAPS);
5866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
5876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
5888a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    private void layoutSenderSpans() {
5898a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira        if (isActivated() && showActivatedText()) {
5908a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            if (mActivatedTextSpan == null) {
5918a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira                mActivatedTextSpan = getActivatedTextSpan();
5928a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            }
5938a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            mHeader.styledSendersString.setSpan(mActivatedTextSpan, 0,
5948a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira                    mHeader.styledMessageInfoStringOffset, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
5958a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira        } else {
5968a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            mHeader.styledSendersString.removeSpan(mActivatedTextSpan);
5978a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira        }
598850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        mHeader.sendersTextView = getSendersTextView();
599850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp    }
600850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp
601850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp    private TextView getSendersTextView() {
602850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        TextView sendersTextView = new TextView(mContext);
603850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        sendersTextView.setMaxLines(1);
604850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        sendersTextView.setEllipsize(TextUtils.TruncateAt.END);
605850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        sendersTextView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
606850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                ViewGroup.LayoutParams.WRAP_CONTENT));
607ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp        int length = (int) sPaint.measureText(mHeader.styledSendersString.toString());
608850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        sendersTextView.setText(mHeader.styledSendersString, TextView.BufferType.SPANNABLE);
609850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        sendersTextView.setWidth(length);
610850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        return sendersTextView;
6118a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    }
6128a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira
6138a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    private CharacterStyle getActivatedTextSpan() {
6148a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira        return CharacterStyle.wrap(sActivatedTextSpan);
6158a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira    }
6168a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira
6170b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    private void layoutSubjectSpans(boolean isUnread) {
6180b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        if (showActivatedText()) {
6190b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            mHeader.subjectTextActivated = createSubject(isUnread, true);
6200b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        }
6210b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        mHeader.subjectText = createSubject(isUnread, false);
6220b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    }
6230b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira
6240b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    private SpannableStringBuilder createSubject(boolean isUnread, boolean activated) {
625732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang        final String subject = filterTag(mHeader.conversation.subject);
626aa1f945612847bc4cf5c8909b8acfab4b5ecf54eMindy Pereira        final String snippet = mHeader.conversation.getSnippet();
627ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        int subjectColor = activated ? sActivatedTextColor : isUnread ? sSubjectTextColorUnead
628ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                : sSubjectTextColorRead;
629ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        int snippetColor = activated ? sActivatedTextColor : isUnread ? sSnippetTextColorUnread
630ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                : sSnippetTextColorRead;
631bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira        SpannableStringBuilder subjectText = Conversation.getSubjectAndSnippetForDisplay(mContext,
632bf9508d3877d05742b2f5d23e1780366d3e1aa2eMindy Pereira                subject, snippet);
6336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (isUnread) {
6340b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            subjectText.setSpan(new StyleSpan(Typeface.BOLD), 0, subject.length(),
6356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
6366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
6370b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        subjectText.setSpan(new ForegroundColorSpan(subjectColor), 0, subject.length(),
6380b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
63934775bdefbccd07f194a7e34c2f89e434c1c1ecbAndy Huang        if (!TextUtils.isEmpty(snippet)) {
6400b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            subjectText.setSpan(new ForegroundColorSpan(snippetColor), subject.length() + 1,
6410b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                    subjectText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
642304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blank        }
6430b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        return subjectText;
6446f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
6456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private int getFontColor(int defaultColor) {
647ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        return isActivated() && mTabletDevice ? sActivatedTextColor
6486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                : defaultColor;
6496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
6506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6510b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    private boolean showActivatedText() {
6520b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        return mTabletDevice;
6530b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    }
6540b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira
6556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private void layoutSubject() {
6560b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        if (showActivatedText()) {
6570b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            mHeader.subjectLayoutActivated =
6580b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                    createSubjectLayout(true, mHeader.subjectTextActivated);
6590b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        }
6600b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        mHeader.subjectLayout = createSubjectLayout(false, mHeader.subjectText);
6610b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    }
6620b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira
6630b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira    private StaticLayout createSubjectLayout(boolean activated,
6640b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            SpannableStringBuilder subjectText) {
6656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTextSize(mCoordinates.subjectFontSize);
666ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        sPaint.setColor(activated ? sActivatedTextColor
667ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                : mHeader.unread ? sSubjectTextColorUnead : sSubjectTextColorRead);
6680b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        StaticLayout subjectLayout = new StaticLayout(subjectText, sPaint,
6696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true);
6700b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        int lineCount = subjectLayout.getLineCount();
6710b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        if (mCoordinates.subjectLineCount < lineCount) {
6720b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            int end = subjectLayout.getLineEnd(mCoordinates.subjectLineCount - 1);
6730b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            subjectLayout = new StaticLayout(subjectText.subSequence(0, end), sPaint,
6740b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                    mCoordinates.subjectWidth, Alignment.ALIGN_NORMAL, 1, 0, true);
6756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
6760b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        return subjectLayout;
6776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
6786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private boolean canFitFragment(int width, int line, int fixedWidth) {
6806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (line == mCoordinates.sendersLineCount) {
6816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            return width + fixedWidth <= mSendersWidth;
6826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        } else {
6836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            return width <= mSendersWidth;
6846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
6856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
6866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private void calculateCoordinates() {
6886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        startTimer(PERF_TAG_CALCULATE_COORDINATES);
6896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTextSize(mCoordinates.dateFontSize);
6916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTypeface(Typeface.DEFAULT);
6926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mDateX = mCoordinates.dateXEnd - (int) sPaint.measureText(mHeader.dateText);
6936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        mPaperclipX = mDateX - ATTACHMENT.getWidth();
6956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
69630fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira        int cellWidth = mContext.getResources().getDimensionPixelSize(R.dimen.folder_cell_width);
6976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
6983fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira        if (ConversationItemViewCoordinates.isWideMode(mMode)) {
6993fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            // Folders are displayed above the date.
7003fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            mFoldersXEnd = mCoordinates.dateXEnd;
7013fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            // In wide mode, the end of the senders should align with
7023fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            // the start of the subject and is based on a max width.
7033fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            mSendersWidth = mCoordinates.sendersWidth;
7043fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira        } else {
7053fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            // In normal mode, the width is based on where the folders or date
7063fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            // (or attachment icon) start.
7073fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira            if (mCoordinates.showFolders) {
708b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (mHeader.paperclip != null) {
709b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    mFoldersXEnd = mPaperclipX;
710b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                } else {
711b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    mFoldersXEnd = mDateX - cellWidth / 2;
712b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
713b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                mSendersWidth = mFoldersXEnd - mCoordinates.sendersX - 2 * cellWidth;
714b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                if (mHeader.folderDisplayer.hasVisibleFolders()) {
715b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                    mSendersWidth -= ConversationItemViewCoordinates.getFoldersWidth(mContext,
716b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                            mMode);
717b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira                }
7186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            } else {
7193fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                int dateAttachmentStart = 0;
7203fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                // Have this end near the paperclip or date, not the folders.
7213fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                if (mHeader.paperclip != null) {
7223fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                    dateAttachmentStart = mPaperclipX;
7233fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                } else {
7243fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                    dateAttachmentStart = mDateX;
7253fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                }
7263fd1f2c4cba9095ccd024ac26187cba6fdfc367bMindy Pereira                mSendersWidth = dateAttachmentStart - mCoordinates.sendersX - cellWidth;
7276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
7286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
7296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
7306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.isLayoutValid(mContext)) {
7316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
7326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            return;
7336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
7346f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
7356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Layout subject.
7366f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        layoutSubject();
7376f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
7386f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Second pass to layout each fragment.
7396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        int sendersY = mCoordinates.sendersY - mCoordinates.sendersAscent;
740ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira
741b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        if (mHeader.styledSenders != null) {
742ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            ellipsizeStyledSenders();
7438a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira            layoutSenderSpans();
744b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        } else {
745ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            // First pass to calculate width of each fragment.
746ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            int totalWidth = 0;
747ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            int fixedWidth = 0;
748ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sPaint.setTextSize(mCoordinates.sendersFontSize);
749ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sPaint.setTypeface(Typeface.DEFAULT);
750ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            for (SenderFragment senderFragment : mHeader.senderFragments) {
751ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                CharacterStyle style = senderFragment.style;
752ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                int start = senderFragment.start;
753ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                int end = senderFragment.end;
754ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                style.updateDrawState(sPaint);
755ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                senderFragment.width = (int) sPaint.measureText(mHeader.sendersText, start, end);
756ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                boolean isFixed = senderFragment.isFixed;
757ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                if (isFixed) {
758ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                    fixedWidth += senderFragment.width;
759ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                }
760ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                totalWidth += senderFragment.width;
761ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            }
762ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira
763ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            if (!ConversationItemViewCoordinates.displaySendersInline(mMode)) {
764ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                sendersY += totalWidth <= mSendersWidth ? mCoordinates.sendersLineHeight / 2 : 0;
765ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            }
76658ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira            totalWidth = ellipsize(fixedWidth, sendersY);
767b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            mHeader.sendersDisplayLayout = new StaticLayout(mHeader.sendersDisplayText, sPaint,
768b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira                    mSendersWidth, Alignment.ALIGN_NORMAL, 1, 0, true);
769b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        }
770b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira
771b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        sPaint.setTextSize(mCoordinates.sendersFontSize);
772b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        sPaint.setTypeface(Typeface.DEFAULT);
773b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        if (mSendersWidth < 0) {
774b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            mSendersWidth = 0;
775b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        }
776b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira
777b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
778b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira    }
779b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira
78058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira    // The rules for displaying ellipsized senders are as follows:
78158ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira    // 1) If there is message info (either a COUNT or DRAFT info to display), it MUST be shown
78258ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira    // 2) If senders do not fit, ellipsize the last one that does fit, and stop
78358ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira    // appending new senders
784ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira    private int ellipsizeStyledSenders() {
785b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        SpannableStringBuilder builder = new SpannableStringBuilder();
78684cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira        float totalWidth = 0;
787b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        boolean ellipsize = false;
78884cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira        float width;
789ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp        SpannableStringBuilder messageInfoString =  mHeader.messageInfoString;
7900c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira        if (messageInfoString.length() > 0) {
7910c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            CharacterStyle[] spans = messageInfoString.getSpans(0, messageInfoString.length(),
7920c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira                    CharacterStyle.class);
7930c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            // There is only 1 character style span; make sure we apply all the
7940c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            // styles to the paint object before measuring.
7950c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            if (spans.length > 0) {
7960c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira                spans[0].updateDrawState(sPaint);
7970c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            }
7980c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            // Paint the message info string to see if we lose space.
7990c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            float messageInfoWidth = sPaint.measureText(messageInfoString.toString());
8000c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira            totalWidth += messageInfoWidth;
8010c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira        }
802ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp       SpannableString prevSender = null;
803ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp       SpannableString ellipsizedText;
804b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        for (SpannableString sender : mHeader.styledSenders) {
805feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira            // There may be null sender strings if there were dupes we had to remove.
806feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira            if (sender == null) {
807feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira                continue;
808feffa26a40e933ad0ff4700e2bf9e0555f0f8470Mindy Pereira            }
80958ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira            // No more width available, we'll only show fixed fragments.
81058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira            if (ellipsize) {
81158ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira                break;
81258ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira            }
8136c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira            CharacterStyle[] spans = sender.getSpans(0, sender.length(), CharacterStyle.class);
8146c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira            // There is only 1 character style span.
8156c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira            if (spans.length > 0) {
8166c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira                spans[0].updateDrawState(sPaint);
8176c2663dc9cade8aff34c462d244e3d72c475c664Mindy Pereira            }
8181152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira            // If there are already senders present in this string, we need to
8191152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira            // make sure we prepend the dividing token
820b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            if (SendersView.sElidedString.equals(sender.toString())) {
821b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                prevSender = sender;
822ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                sender = copyStyles(spans, sElidedPaddingToken + sender + sElidedPaddingToken);
823b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            } else if (builder.length() > 0
824b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                    && (prevSender == null || !SendersView.sElidedString.equals(prevSender
825b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                            .toString()))) {
826b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                prevSender = sender;
827ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                sender = copyStyles(spans, sSendersSplitToken + sender);
828b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira            } else {
829b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira                prevSender = sender;
8301152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira            }
831ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp            if (spans.length > 0) {
832ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp                spans[0].updateDrawState(sPaint);
833ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp            }
8341152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira            // Measure the width of the current sender and make sure we have space
835b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            width = (int) sPaint.measureText(sender.toString());
836ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            if (width + totalWidth > mSendersWidth) {
837b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira                // The text is too long, new line won't help. We have to
838b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira                // ellipsize text.
8391152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                ellipsize = true;
840ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp                width = mSendersWidth - totalWidth; // ellipsis width?
8411152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                ellipsizedText = copyStyles(spans,
8421152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                        TextUtils.ellipsize(sender, sPaint, width, TruncateAt.END));
8431152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                width = (int) sPaint.measureText(ellipsizedText.toString());
8441152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira            } else {
8451152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                ellipsizedText = null;
846b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            }
847b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            totalWidth += width;
848b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira
849b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            final CharSequence fragmentDisplayText;
850b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            if (ellipsizedText != null) {
851b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira                fragmentDisplayText = ellipsizedText;
852b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            } else {
8531152c02a415f5b93bdecc5733a7372dca7d9ecd3Mindy Pereira                fragmentDisplayText = sender;
854b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            }
855b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira            builder.append(fragmentDisplayText);
856b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        }
85701bb8d91c8ea039518ee07c8ac83e4e42cd81739Mindy Pereira        mHeader.styledMessageInfoStringOffset = builder.length();
8588a6eb44e688ce082597978def2042ea8376b34b2Mindy Pereira        if (messageInfoString != null) {
85958ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira            builder.append(messageInfoString);
86058ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira        }
861b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        mHeader.styledSendersString = builder;
86284cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira        return (int)totalWidth;
86384cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira    }
86484cef5e3457338d22dc3e96dc6feeaf9e50e4d57Mindy Pereira
865d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira    private SpannableString copyStyles(CharacterStyle[] spans, CharSequence newText) {
866d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira        SpannableString s = new SpannableString(newText);
867d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira        if (spans != null && spans.length > 0) {
868d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira            s.setSpan(spans[0], 0, s.length(), 0);
869d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira        }
870d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira        return s;
871d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira    }
872d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereira
87358ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira    private int ellipsize(int fixedWidth, int sendersY) {
874b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        int totalWidth = 0;
8756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        int currentLine = 1;
8766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        boolean ellipsize = false;
8776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        for (SenderFragment senderFragment : mHeader.senderFragments) {
8786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            CharacterStyle style = senderFragment.style;
8796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int start = senderFragment.start;
8806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int end = senderFragment.end;
8816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int width = senderFragment.width;
8826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            boolean isFixed = senderFragment.isFixed;
8836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            style.updateDrawState(sPaint);
8846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
8856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // No more width available, we'll only show fixed fragments.
8866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (ellipsize && !isFixed) {
8876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                senderFragment.shouldDisplay = false;
8886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                continue;
8896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
8906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
8916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            // New line and ellipsize text if needed.
8926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            senderFragment.ellipsizedText = null;
8936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (isFixed) {
8946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                fixedWidth -= width;
8956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
8966f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (!canFitFragment(totalWidth + width, currentLine, fixedWidth)) {
8976f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                // The text is too long, new line won't help. We have to
8986f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                // ellipsize text.
8996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                if (totalWidth == 0) {
9006f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    ellipsize = true;
9016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                } else {
9026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    // New line.
9036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    if (currentLine < mCoordinates.sendersLineCount) {
9046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        currentLine++;
9056f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        sendersY += mCoordinates.sendersLineHeight;
9066f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        totalWidth = 0;
9076f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        // The text is still too long, we have to ellipsize
9086f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        // text.
9096f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        if (totalWidth + width > mSendersWidth) {
9106f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                            ellipsize = true;
9116f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        }
9126f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    } else {
9136f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        ellipsize = true;
9146f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    }
9156f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                }
9166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
9176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                if (ellipsize) {
9186f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    width = mSendersWidth - totalWidth;
9196f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    // No more new line, we have to reserve width for fixed
9206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    // fragments.
9216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    if (currentLine == mCoordinates.sendersLineCount) {
9226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        width -= fixedWidth;
9236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    }
9246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    senderFragment.ellipsizedText = TextUtils.ellipsize(
9256f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                            mHeader.sendersText.substring(start, end), sPaint, width,
9266f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                            TruncateAt.END).toString();
9276f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    width = (int) sPaint.measureText(senderFragment.ellipsizedText);
9286f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                }
9296f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
9306f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            senderFragment.shouldDisplay = true;
9316f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            totalWidth += width;
932d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang
933d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            final CharSequence fragmentDisplayText;
934d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            if (senderFragment.ellipsizedText != null) {
935d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang                fragmentDisplayText = senderFragment.ellipsizedText;
936d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            } else {
937d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang                fragmentDisplayText = mHeader.sendersText.substring(start, end);
938d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            }
939d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            final int spanStart = mHeader.sendersDisplayText.length();
940d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            mHeader.sendersDisplayText.append(fragmentDisplayText);
941d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang            mHeader.sendersDisplayText.setSpan(senderFragment.style, spanStart,
942d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang                    mHeader.sendersDisplayText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
9436f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
944b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira        return totalWidth;
9456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
9466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
9476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    /**
9486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     * If the subject contains the tag of a mailing-list (text surrounded with
9496f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     * []), return the subject with that tag ellipsized, e.g.
9506f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     * "[android-gmail-team] Hello" -> "[andr...] Hello"
9516f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira     */
9526f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private String filterTag(String subject) {
9536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        String result = subject;
9546f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        String formatString = getContext().getResources().getString(R.string.filtered_tag);
9556f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (!TextUtils.isEmpty(subject) && subject.charAt(0) == '[') {
9566f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int end = subject.indexOf(']');
9576f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (end > 0) {
9586f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                String tag = subject.substring(1, end);
9596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                result = String.format(formatString, Utils.ellipsize(tag, 7),
9606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        subject.substring(end + 1));
9616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
9626f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
9636f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        return result;
9646f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
9656f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
9666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    @Override
9676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    protected void onDraw(Canvas canvas) {
9686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Check mark.
9696f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.checkboxVisible) {
970c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira            Bitmap checkmark = mChecked ? CHECKMARK_ON : CHECKMARK_OFF;
9716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.drawBitmap(checkmark, mCoordinates.checkmarkX, mCoordinates.checkmarkY, sPaint);
9726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
9736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
9746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Personal Level.
9753cb938f638cc3cec08c9c42d20192e65b1e7d343Mindy Pereira        if (mCoordinates.showPersonalLevel && mHeader.personalLevelBitmap != null) {
9766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.drawBitmap(mHeader.personalLevelBitmap, mCoordinates.personalLevelX,
9776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    mCoordinates.personalLevelY, sPaint);
9786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
9796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
9806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Senders.
9818d69d4e10a9a36ff790babb2f3a098a12d0dc732Marc Blank        boolean isUnread = mHeader.unread;
982ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        // Old style senders; apply text colors/ sizes/ styling.
983850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        canvas.save();
984850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp        if (mHeader.sendersDisplayLayout != null) {
985ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira            sPaint.setTextSize(mCoordinates.sendersFontSize);
98677d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira            sPaint.setTypeface(SendersView.getTypeface(isUnread));
987850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            sPaint.setColor(getFontColor(isUnread ? sSendersTextColorUnread
988850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                    : sSendersTextColorRead));
989850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            canvas.translate(mCoordinates.sendersX,
990850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                    mCoordinates.sendersY + mHeader.sendersDisplayLayout.getTopPadding());
991850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            mHeader.sendersDisplayLayout.draw(canvas);
992ffd21a08c89f78adc2ee7a07b1afe6163c5f1607mindyp        } else {
993850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            canvas.translate(mCoordinates.sendersX,
994850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp                    mCoordinates.sendersY + sSendersTextViewTopPadding);
995850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            mHeader.sendersTextView.layout(0, 0, mSendersWidth, sSendersTextViewHeight);
996850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp            mHeader.sendersTextView.draw(canvas);
997ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        }
998d7a4ad903cd77a2cd3ad44c7c456b48c7d47e599Andy Huang        canvas.restore();
9996f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1000850c55ee2cab6b1c224366c66502f5d5f55018ebmindyp
10016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Subject.
10026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTextSize(mCoordinates.subjectFontSize);
10036f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTypeface(Typeface.DEFAULT);
10046f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        canvas.save();
10050b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        if (isActivated() && showActivatedText()) {
10060b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            if (mHeader.subjectLayoutActivated != null) {
10070b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                canvas.translate(mCoordinates.subjectX, mCoordinates.subjectY
10080b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                        + mHeader.subjectLayoutActivated.getTopPadding());
10090b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira                mHeader.subjectLayoutActivated.draw(canvas);
10100b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira            }
10110b686764015284889d98b8e9f1abea8b27ce26bdMindy Pereira        } else if (mHeader.subjectLayout != null) {
10124f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira            canvas.translate(mCoordinates.subjectX,
10134f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira                    mCoordinates.subjectY + mHeader.subjectLayout.getTopPadding());
10144f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira            mHeader.subjectLayout.draw(canvas);
10154f4334983e01c5f72ef0b14d72356a5736c82decMindy Pereira        }
10166f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        canvas.restore();
10176f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1018b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        // Folders.
1019b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        if (mCoordinates.showFolders) {
1020b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira            mHeader.folderDisplayer.drawFolders(canvas, mCoordinates, mFoldersXEnd, mMode);
1021b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira        }
1022b5080d5335d2aa445a660ad426ab008750be24cbMindy Pereira
102392939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        // If this folder has a color (combined view/Email), show it here
102492939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        if (mHeader.conversation.color != 0) {
102592939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            sFoldersPaint.setColor(mHeader.conversation.color);
102692939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            sFoldersPaint.setStyle(Paint.Style.FILL);
102792939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            int width = ConversationItemViewCoordinates.getColorBlockWidth(mContext);
102892939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            int height = ConversationItemViewCoordinates.getColorBlockHeight(mContext);
102992939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank            canvas.drawRect(mCoordinates.dateXEnd - width, 0, mCoordinates.dateXEnd,
103092939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank                    height, sFoldersPaint);
103192939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank        }
103292939fc7b40a56e17fb0d2fde987133ca1614e29Marc Blank
10336f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Date background: shown when there is an attachment or a visible
103430fd47bf1947da5ad813cb957b6cbe569dce563aMindy Pereira        // folder.
10356f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (!isActivated()
1036280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira                && (mHeader.conversation.hasAttachments ||
1037280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira                        (mHeader.folderDisplayer != null
1038280dbf201cbc555ee59edc4dfe459aebe4ffceadMindy Pereira                            && mHeader.folderDisplayer.hasVisibleFolders()))
10390944e5e69312666b89fda025430b7cf03bca4305Mindy Pereira                && ConversationItemViewCoordinates.showAttachmentBackground(mMode)) {
1040732600e38891db139bae02dc91dd0c5b0987e8e9Andy Huang            int leftOffset = (mHeader.conversation.hasAttachments ? mPaperclipX : mDateX)
1041ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira                    - sDateBackgroundPaddingLeft;
104247ccb45dff1329d5ddac33fb71674048f8c7f51aMindy Pereira            int top = mCoordinates.showFolders ? mCoordinates.foldersY : mCoordinates.dateY;
1043bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            mHeader.dateBackground = getDateBackground(mHeader.conversation.hasAttachments);
1044bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            canvas.drawBitmap(mHeader.dateBackground, leftOffset, top, sPaint);
10456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        } else {
10466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            mHeader.dateBackground = null;
10476f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
10486f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
104954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira        // Draw the reply state. Draw nothing if neither replied nor forwarded.
105054467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira        if (mCoordinates.showReplyState) {
105154467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            if (mHeader.hasBeenRepliedTo && mHeader.hasBeenForwarded) {
105254467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                canvas.drawBitmap(STATE_REPLIED_AND_FORWARDED, mCoordinates.replyStateX,
105354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                        mCoordinates.replyStateY, null);
105454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            } else if (mHeader.hasBeenRepliedTo) {
105554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                canvas.drawBitmap(STATE_REPLIED, mCoordinates.replyStateX,
105654467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                        mCoordinates.replyStateY, null);
105754467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            } else if (mHeader.hasBeenForwarded) {
105854467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                canvas.drawBitmap(STATE_FORWARDED, mCoordinates.replyStateX,
105954467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira                        mCoordinates.replyStateY, null);
10608d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira            } else if (mHeader.isInvite) {
1061d5ac9c16e8955abe8366fd1185b86d8bd7c5ac60Mindy Pereira                canvas.drawBitmap(STATE_CALENDAR_INVITE, mCoordinates.replyStateX,
10628d83c8a0c9c01ce5ed9381f2765b3ba59948710fMindy Pereira                        mCoordinates.replyStateY, null);
106354467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira            }
106454467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira        }
106554467a21dce72130bb04eb5aa1c9813d88308a80Mindy Pereira
10666f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Date.
10676f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTextSize(mCoordinates.dateFontSize);
10686f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        sPaint.setTypeface(Typeface.DEFAULT);
1069ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        sPaint.setColor(sDateTextColor);
10706f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        drawText(canvas, mHeader.dateText, mDateX, mCoordinates.dateY - mCoordinates.dateAscent,
10716f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                sPaint);
10726f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
10736f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Paper clip icon.
10746f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.paperclip != null) {
10756f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.drawBitmap(mHeader.paperclip, mPaperclipX, mCoordinates.paperclipY, sPaint);
10766f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
10776f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
10786f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (mHeader.faded) {
10796f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int fadedColor = -1;
10806f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            if (sFadedActivatedColor == -1) {
10816f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                sFadedActivatedColor = mContext.getResources().getColor(
10826f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                        R.color.faded_activated_conversation_header);
10836f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
10846f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            fadedColor = sFadedActivatedColor;
10856f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            int restoreState = canvas.save();
10866f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            Rect bounds = canvas.getClipBounds();
10876f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.clipRect(bounds.left, bounds.top, bounds.right
10886f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    - mContext.getResources().getDimensionPixelSize(R.dimen.triangle_width),
10896f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    bounds.bottom);
10906f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.drawARGB(Color.alpha(fadedColor), Color.red(fadedColor),
10916f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira                    Color.green(fadedColor), Color.blue(fadedColor));
10926f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            canvas.restoreToCount(restoreState);
10936f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
10946f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
10956f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        // Star.
10964f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira        canvas.drawBitmap(getStarBitmap(), mCoordinates.starX, mCoordinates.starY, sPaint);
10974f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira    }
10984f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira
10994f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira    private Bitmap getStarBitmap() {
11004f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira        return mHeader.conversation.starred ? STAR_ON : STAR_OFF;
11016f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
11026f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
1103bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira    private Bitmap getDateBackground(boolean hasAttachments) {
1104ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        int leftOffset = (hasAttachments ? mPaperclipX : mDateX) - sDateBackgroundPaddingLeft;
1105bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira        if (hasAttachments) {
1106bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            if (sDateBackgroundAttachment == null) {
1107bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira                sDateBackgroundAttachment = Bitmap.createScaledBitmap(DATE_BACKGROUND, mViewWidth
1108bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira                        - leftOffset, sDateBackgroundHeight, false);
1109bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            }
1110bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            return sDateBackgroundAttachment;
1111bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira        } else {
1112bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            if (sDateBackgroundNoAttachment == null) {
1113bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira                sDateBackgroundNoAttachment = Bitmap.createScaledBitmap(DATE_BACKGROUND, mViewWidth
1114bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira                        - leftOffset, sDateBackgroundHeight, false);
1115bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            }
1116bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira            return sDateBackgroundNoAttachment;
1117bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira        }
1118bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira    }
1119bf19cb00a3cc0f65b6b6e5ce8553f53c03a3b717Mindy Pereira
11206f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private void drawText(Canvas canvas, CharSequence s, int x, int y, TextPaint paint) {
11216f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        canvas.drawText(s, 0, s.length(), x, y, paint);
11226f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
11236f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira
11246f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    private void updateBackground(boolean isUnread) {
11255c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        if (mBackgroundOverride != -1) {
1126d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira            // If the item is animating, we use a color to avoid shrinking a 9-patch
1127d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira            // and getting weird artifacts from the overlap.
11285c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira            setBackgroundColor(mBackgroundOverride);
1129d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira            return;
1130d1ee8822384cdfa5001572245c72f9996a39a197Mindy Pereira        }
11310d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal        final boolean isListOnTablet = mTabletDevice && mActivity.getViewMode().isListMode();
11326f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        if (isUnread) {
11330d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal            if (isListOnTablet) {
11349d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                if (mChecked) {
11359d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.list_conversation_wide_unread_selected_holo);
11369d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                } else {
11379d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.conversation_wide_unread_selector);
11389d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                }
11396f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            } else {
11409d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                if (mChecked) {
11419d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setCheckedActivatedBackground();
11429d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                } else {
11439d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.conversation_unread_selector);
11449d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                }
11456f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
11466f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        } else {
11470d8015eff2b1eba829e70750455d965eba4a8896Vikram Aggarwal            if (isListOnTablet) {
11489d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                if (mChecked) {
11499d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.list_conversation_wide_read_selected_holo);
11509d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                } else {
11519d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.conversation_wide_read_selector);
11529d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                }
11536f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            } else {
11549d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                if (mChecked) {
11559d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setCheckedActivatedBackground();
11569d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                } else {
11579d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                    setBackgroundResource(R.drawable.conversation_read_selector);
11589d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira                }
11596f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira            }
11606f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira        }
11616f92de64bbdf1ea6c4cd9774fc96921a10c266d7Mindy Pereira    }
1162c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira
11639d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira    private void setCheckedActivatedBackground() {
1164fa131a2ff399fd1d544f759b063268fb4e8a3e70Vikram Aggarwal        if (isActivated() && mTabletDevice) {
11659d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira            setBackgroundResource(R.drawable.list_arrow_selected_holo);
11669d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira        } else {
11679d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira            setBackgroundResource(R.drawable.list_selected_holo);
11689d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira        }
11699d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira    }
11709d59a9a272abc78564428dd204d3616317c96b4bMindy Pereira
1171c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    /**
1172c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira     * Toggle the check mark on this view and update the conversation
1173c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira     */
1174c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    public void toggleCheckMark() {
1175b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira        if (mHeader != null && mHeader.conversation != null) {
1176b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            mChecked = !mChecked;
1177b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            Conversation conv = mHeader.conversation;
1178b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            // Set the list position of this item in the conversation
11791ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            ListView listView = getListView();
1180b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            conv.position = mChecked && listView != null ? listView.getPositionForView(this)
1181b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira                    : Conversation.NO_POSITION;
1182b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            if (mSelectedConversationSet != null) {
1183b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira                mSelectedConversationSet.toggle(this, conv);
1184b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            }
1185bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook            // We update the background after the checked state has changed now
1186bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook            // that
1187bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook            // we have a selected background asset. Setting the background
1188bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook            // usually
1189b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            // waits for a layout pass, but we don't need a full layout, just an
1190b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            // update to the background.
1191b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira            requestLayout();
1192d247dc966bca1ed303039c2893c54979d448a336Vikram Aggarwal        }
1193c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    }
1194c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira
1195c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    /**
1196866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * Return if the checkbox for this item is checked.
1197866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     */
1198866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public boolean isChecked() {
1199866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        return mChecked;
1200866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
1201866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1202866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    /**
1203c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira     * Toggle the star on this view and update the conversation.
1204c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira     */
1205866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public void toggleStar() {
12064f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira        mHeader.conversation.starred = !mHeader.conversation.starred;
12074f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira        Bitmap starBitmap = getStarBitmap();
1208c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira        postInvalidate(mCoordinates.starX, mCoordinates.starY, mCoordinates.starX
12094f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira                + starBitmap.getWidth(),
12104f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira                mCoordinates.starY + starBitmap.getHeight());
1211bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook        ConversationCursor cursor = (ConversationCursor)mAdapter.getCursor();
1212bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook        cursor.updateBoolean(mContext, mHeader.conversation, ConversationColumns.STARRED,
12134f2224c70d4d07df85b325fa3faf78218f92aae6Mindy Pereira                mHeader.conversation.starred);
1214c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    }
1215c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira
1216866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    private boolean isTouchInCheckmark(float x, float y) {
1217c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira        // Everything before senders and include a touch slop.
1218ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        return mHeader.checkboxVisible && x < mCoordinates.sendersX + sTouchSlop;
1219c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    }
1220c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira
1221866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    private boolean isTouchInStar(float x, float y) {
1222c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira        // Everything after the star and include a touch slop.
1223ee0c85d6d0ad72cfdf3edce935a598e2655ae65bMindy Pereira        return x > mCoordinates.starX - sTouchSlop;
1224c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    }
1225c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira
1226304a91eab01d67c8b5ef134b3bfe922fb6ab102fMarc Blank    @Override
1227a538984fcc19e7624f2650b119ede39bf1f35846mindyp    public boolean canChildBeDismissed() {
1228a538984fcc19e7624f2650b119ede39bf1f35846mindyp        return true;
1229a538984fcc19e7624f2650b119ede39bf1f35846mindyp    }
1230a538984fcc19e7624f2650b119ede39bf1f35846mindyp
1231a538984fcc19e7624f2650b119ede39bf1f35846mindyp    @Override
1232a538984fcc19e7624f2650b119ede39bf1f35846mindyp    public void dismiss() {
12335254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        SwipeableListView listView = this.getListView();
12345254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        if (listView != null) {
12355254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp            getListView().dismissChild(this);
12365254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        }
12375bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira    }
12385bcd7e9f994624eea184a60ff50a3d71b5710582Mindy Pereira
1239b6b174fb3a8f58a2c81e035917ebad8ab45b88aeMindy Pereira    /**
1240866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * ConversationItemView is given the first chance to handle touch events.
1241866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     */
1242c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    @Override
1243c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    public boolean onTouchEvent(MotionEvent event) {
12441e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira        int x = (int) event.getX();
12451e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira        int y = (int) event.getY();
1246f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        if (!mSwipeEnabled) {
1247f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira            return onTouchEventNoSwipe(event);
1248f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        }
1249c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira        switch (event.getAction()) {
1250c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira            case MotionEvent.ACTION_DOWN:
1251960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                if (isTouchInCheckmark(x, y) || isTouchInStar(x, y)) {
1252960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                    mDownEvent = true;
1253960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                    return true;
1254960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                }
1255c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                break;
1256c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira            case MotionEvent.ACTION_UP:
1257c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                if (mDownEvent) {
1258866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                    if (isTouchInCheckmark(x, y)) {
1259c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                        // Touch on the check mark
1260960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                        mDownEvent = false;
1261c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                        toggleCheckMark();
1262960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                        return true;
1263866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                    } else if (isTouchInStar(x, y)) {
1264c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                        // Touch on the star
1265960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                        mDownEvent = false;
1266c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                        toggleStar();
1267960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira                        return true;
1268c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                    }
1269c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                }
1270c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira                break;
1271c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira        }
1272ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal        // Let View try to handle it as well.
1273960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        boolean handled = super.onTouchEvent(event);
1274960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        if (event.getAction() == MotionEvent.ACTION_DOWN) {
1275960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira            return true;
1276960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        }
1277960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        return handled;
1278c1b239dae7848b8783cb61964f870f8e18e8cc4fMindy Pereira    }
1279866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1280960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira    @Override
1281960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira    public boolean performClick() {
1282960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        boolean handled = super.performClick();
1283960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        ListView list = getListView();
1284960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        if (list != null) {
1285960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira            int pos = list.getPositionForView(this);
1286960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira            list.performItemClick(this, pos, mHeader.conversation.id);
1287960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        }
1288960fea746ff82480cccf6a945bfaeab1689c7138Mindy Pereira        return handled;
12891e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira    }
12901e946db1a0e20a92361cf1c86d8b28a1f878fdbcMindy Pereira
1291a538984fcc19e7624f2650b119ede39bf1f35846mindyp    private SwipeableListView getListView() {
12925254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        SwipeableListView v = (SwipeableListView) ((SwipeableConversationItemView) getParent())
12935254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp                .getListView();
12945254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        if (v == null) {
12955254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp            v = mAdapter.getListView();
12965254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        }
12975254486a8c37cdf2b579aa7a3b9c8eb7324062bcmindyp        return v;
12981ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira    }
12991ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira
1300f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    private boolean onTouchEventNoSwipe(MotionEvent event) {
1301f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        boolean handled = true;
1302f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira
1303f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        int x = (int) event.getX();
1304f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        int y = (int) event.getY();
1305f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        switch (event.getAction()) {
1306f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira            case MotionEvent.ACTION_DOWN:
1307f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                mDownEvent = true;
1308f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                // In order to allow the down event and subsequent move events
1309f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                // to bubble to the swipe handler, we need to return that all
1310f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                // down events are handled.
1311f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                handled = isTouchInCheckmark(x, y) || isTouchInStar(x, y);
1312f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                break;
1313f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira            case MotionEvent.ACTION_CANCEL:
1314f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                mDownEvent = false;
1315f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                break;
1316f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira            case MotionEvent.ACTION_UP:
1317f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                if (mDownEvent) {
1318f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // ConversationItemView gets the first chance to handle up
1319f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // events if there was a down event and there was no move
1320f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // event in between. In this case, ConversationItemView
1321f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // received the down event, and then an up event in the
1322f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // same location (+/- slop). Treat this as a click on the
1323f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // view or on a specific part of the view.
1324f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    if (isTouchInCheckmark(x, y)) {
1325f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                        // Touch on the check mark
1326f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                        toggleCheckMark();
1327f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    } else if (isTouchInStar(x, y)) {
1328f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                        // Touch on the star
1329f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                        toggleStar();
1330f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    }
1331f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    handled = true;
1332f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                } else {
1333f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // There was no down event that this view was made aware of,
1334f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    // therefore it cannot handle it.
1335f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                    handled = false;
1336f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                }
1337f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira                break;
1338f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        }
1339f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira
1340ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal        // Let View try to handle it as well.
1341ac9687c359d06ffd26a270906325dacef531ef53Vikram Aggarwal        return handled || super.onTouchEvent(event);
1342f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    }
1343f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira
1344866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    /**
13455c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira     * Reset any state associated with this conversation item view so that it
13465c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira     * can be reused.
13475c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira     */
13485c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    public void reset() {
13495c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        mBackgroundOverride = -1;
13505c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        setAlpha(1);
13515c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        setTranslationX(0);
13525c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        setAnimatedHeight(-1);
13535c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    }
13545c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira
13555c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    /**
1356866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * Grow the height of the item and fade it in when bringing a conversation
1357866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * back from a destructive action.
1358866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * @param listener
1359866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     */
1360bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    public void startSwipeUndoAnimation(ViewMode viewMode, final AnimatorListener listener) {
1361067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator undoAnimator = createTranslateXAnimation(true);
13626c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        undoAnimator.addListener(listener);
1363350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        undoAnimator.start();
1364866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
1365866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1366bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    /**
1367bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira     * Grow the height of the item and fade it in when bringing a conversation
1368bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira     * back from a destructive action.
1369bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira     * @param listener
1370bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira     */
1371bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    public void startUndoAnimation(ViewMode viewMode, final AnimatorListener listener) {
1372bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        int minHeight = ConversationItemViewCoordinates.getMinHeight(mContext, viewMode);
1373bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        setMinimumHeight(minHeight);
1374067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        mAnimatedHeight = 0;
1375067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator height = createHeightAnimation(true);
1376067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        Animator fade = ObjectAnimator.ofFloat(this, "itemAlpha", 0, 1.0f);
1377067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        fade.setDuration(sShrinkAnimationDuration);
1378067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        fade.setInterpolator(new DecelerateInterpolator(2.0f));
1379067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        AnimatorSet transitionSet = new AnimatorSet();
1380067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        transitionSet.playTogether(height, fade);
1381067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        transitionSet.addListener(listener);
1382067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        transitionSet.start();
1383067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    }
1384067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira
1385067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    /**
1386067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira     * Grow the height of the item and fade it in when bringing a conversation
1387067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira     * back from a destructive action.
1388067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira     * @param listener
1389067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira     */
1390067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    public void startDestroyWithSwipeAnimation(final AnimatorListener listener) {
1391067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator slide = createTranslateXAnimation(false);
1392067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator height = createHeightAnimation(false);
1393bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        AnimatorSet transitionSet = new AnimatorSet();
1394067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        transitionSet.playSequentially(slide, height);
1395067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        transitionSet.addListener(listener);
1396bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        transitionSet.start();
1397bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    }
1398bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira
1399067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    private ObjectAnimator createTranslateXAnimation(boolean show) {
1400067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        final float start = show ? sUndoAnimationOffset : 0f;
1401067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        final float end = show ? 0f : sUndoAnimationOffset;
1402067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator slide = ObjectAnimator.ofFloat(this, "translationX", start, end);
1403067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        slide.setInterpolator(new DecelerateInterpolator(2.0f));
1404067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        slide.setDuration(sSlideAnimationDuration);
1405067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        return slide;
1406067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    }
1407067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira
14085c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    public void startDestroyAnimation(final AnimatorListener listener) {
14095c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        ObjectAnimator height = createHeightAnimation(false);
14105c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        int minHeight = ConversationItemViewCoordinates.getMinHeight(mContext,
14115c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira                mActivity.getViewMode());
14125c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        setMinimumHeight(0);
14135c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        mBackgroundOverride = sAnimatingBackgroundColor;
14145c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        setBackgroundColor(mBackgroundOverride);
14155c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        mAnimatedHeight = minHeight;
14165c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        height.addListener(listener);
14175c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira        height.start();
14185c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira    }
14195c16f82f9916b8d21fd36ac7c460811e59ba6614Mindy Pereira
1420067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    private ObjectAnimator createHeightAnimation(boolean show) {
1421067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        int minHeight = ConversationItemViewCoordinates.getMinHeight(getContext(),
1422067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira                mActivity.getViewMode());
1423067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        final int start = show ? 0 : minHeight;
1424067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        final int end = show ? minHeight : 0;
1425067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        ObjectAnimator height = ObjectAnimator.ofInt(this, "animatedHeight", start, end);
1426067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        height.setInterpolator(new DecelerateInterpolator(2.0f));
1427067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        height.setDuration(sShrinkAnimationDuration);
1428067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira        return height;
1429067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira    }
1430067ef97264240a2c3f9172a9ab88ba43fef7c475Mindy Pereira
1431bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    // Used by animator
1432bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    @SuppressWarnings("unused")
1433bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    public void setItemAlpha(float alpha) {
1434bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        setAlpha(alpha);
1435bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        invalidate();
1436bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    }
1437bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira
1438bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    // Used by animator
1439bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    @SuppressWarnings("unused")
1440bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    public void setAnimatedHeight(int height) {
1441bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        mAnimatedHeight = height;
1442bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        requestLayout();
1443bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira    }
1444bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira
1445350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira    @Override
1446350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1447bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        if (mAnimatedHeight == -1) {
1448bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira            int height = measureHeight(heightMeasureSpec,
1449e7d783d726236cb090bba1baed1ea44f743ad788Mindy Pereira                    ConversationItemViewCoordinates.getMode(mContext, mActivity.getViewMode()));
1450bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira            setMeasuredDimension(widthMeasureSpec, height);
1451bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        } else {
1452bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mAnimatedHeight);
1453bdb43d559dfba09752e95ca88f73ca566dcbb86fMindy Pereira        }
1454866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
1455866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1456350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira    /**
1457350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira     * Determine the height of this view.
1458350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira     * @param measureSpec A measureSpec packed into an int
1459350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira     * @param mode The current mode of this view
1460350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira     * @return The height of the view, honoring constraints from measureSpec
1461350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira     */
1462350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira    private int measureHeight(int measureSpec, int mode) {
1463350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        int result = 0;
1464350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        int specMode = MeasureSpec.getMode(measureSpec);
1465350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        int specSize = MeasureSpec.getSize(measureSpec);
1466350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira
1467350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        if (specMode == MeasureSpec.EXACTLY) {
1468350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            // We were told how big to be
1469350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            result = specSize;
1470350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        } else {
1471350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            // Measure the text
1472350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            result = ConversationItemViewCoordinates.getHeight(mContext, mode);
1473350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            if (specMode == MeasureSpec.AT_MOST) {
1474350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira                // Respect AT_MOST value if that was what is called for by
1475350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira                // measureSpec
1476350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira                result = Math.min(result, specSize);
1477350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira            }
1478350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        }
1479350acdc75af67425aa3f8b6e4f889d4828ce8705Mindy Pereira        return result;
1480866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
1481866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1482866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    /**
1483866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     * Get the current position of this conversation item in the list.
1484866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira     */
1485866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public int getPosition() {
1486866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        return mHeader != null && mHeader.conversation != null ?
1487866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                mHeader.conversation.position : -1;
1488866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
1489acf6039a23382f18c35f6b487d90d53cb67b5858Mindy Pereira
14906c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    @Override
1491a538984fcc19e7624f2650b119ede39bf1f35846mindyp    public View getSwipeableView() {
14926c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        return this;
14936c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    }
1494bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook}
1495