Merge "Fix overlapping unread and name in drawer" into jb-ub-mail-ur9
diff --git a/res/layout/conversation_item_view_normal_spacious.xml b/res/layout/conversation_item_view_normal_spacious.xml
new file mode 100644
index 0000000..85c90f5
--- /dev/null
+++ b/res/layout/conversation_item_view_normal_spacious.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 Google Inc.
+     Licensed to The Android Open Source Project.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This layout is used as a template to create custom view CanvasConversationHeaderView
+    in normal mode. To be able to get the correct measurements, every source field should
+    be populated with data here. E.g:
+    - Text View should set text to a random long string (android:text="@string/long_string")
+    - Image View should set source to a specific asset -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="1dp"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="22dp"
+        android:layout_marginRight="16dp"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/checkmark"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="16dp"
+            android:layout_gravity="center_vertical"
+            android:src="@drawable/btn_check_on_normal_holo_light" />
+
+        <View
+            android:id="@+id/contact_image"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_marginRight="16dp"
+            android:layout_marginTop="16dp"
+            android:layout_marginBottom="16dp" />
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical">
+
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <!-- these views overlap horizontally, that's okay. -->
+                <!-- we are only interested in the left edge of senders and the right edge -->
+                <!-- of the date. -->
+                <!-- sendersWidth, clipX, and dateX are dynamically determined later. -->
+
+                <FrameLayout
+                    android:id="@+id/senders_decoration"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content">
+
+                    <!-- for Email -->
+                    <!-- top margin should be 16dp, but the asset has 2dp built-in padding -->
+                    <ImageView
+                        android:id="@+id/reply_state"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="14dp"
+                        android:layout_marginRight="8dp"
+                        android:src="@drawable/ic_badge_reply_holo_light" />
+
+                    <!-- for Gmail -->
+                    <ImageView
+                        android:id="@+id/personal_indicator"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="15dp"
+                        android:layout_marginLeft="-2dp"
+                        android:layout_marginRight="2dp"
+                        android:src="@drawable/ic_email_caret_single" />
+
+                </FrameLayout>
+
+                <TextView
+                    android:id="@+id/senders"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_toRightOf="@id/senders_decoration"
+                    android:layout_marginTop="16dp"
+                    android:textSize="18sp"
+                    android:lines="1"
+                    android:includeFontPadding="false"
+                    android:text="@string/long_string" />
+
+                <TextView
+                    android:id="@+id/date"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:layout_marginTop="16dp"
+                    android:paddingLeft="8dp"
+                    android:textSize="12sp"
+                    android:lines="1"
+                    android:includeFontPadding="false"
+                    android:text="@string/long_string" />
+
+                <!-- top margin should be 16dp, but the asset has 8dp built-in padding -->
+                <!-- left padding should be 8dp, but the asset has 2dp built-in padding -->
+                <ImageView
+                    android:id="@+id/paperclip"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_toLeftOf="@id/date"
+                    android:layout_marginTop="8dp"
+                    android:paddingLeft="6dp"
+                    android:src="@drawable/ic_attachment_holo_light" />
+
+                <!-- for Email -->
+                <View android:id="@+id/color_block"
+                    android:layout_width="@dimen/color_block_width"
+                    android:layout_height="@dimen/color_block_height"
+                    android:layout_alignParentRight="true" />
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="16dp">
+
+                <ImageView
+                    android:id="@+id/star"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:src="@drawable/btn_star_off_normal_email_holo_light" />
+
+                <!-- we assume the star asset is less than 48dp wide -->
+                <TextView
+                    android:id="@+id/subject"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_toLeftOf="@id/star"
+                    android:layout_marginRight="14dp"
+                    android:lines="2"
+                    android:textSize="13sp"
+                    android:includeFontPadding="false"
+                    android:text="@string/long_string" />
+
+            </RelativeLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/attachment_previews"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginTop="@dimen/attachment_preview_margin_top"
+        android:layout_marginLeft="@dimen/attachment_preview_margin_side"
+        android:layout_marginRight="@dimen/attachment_preview_margin_side"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/folders"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="-16dp"
+        android:fontFamily="sans-serif-light"
+        android:includeFontPadding="false"
+        android:text="@string/long_string"
+        android:textSize="11sp"
+        android:lines="1"
+        android:minHeight="16dp" />
+
+</LinearLayout>
diff --git a/res/layout/drawer_empty_view.xml b/res/layout/drawer_empty_view.xml
index f125b76..788debd 100644
--- a/res/layout/drawer_empty_view.xml
+++ b/res/layout/drawer_empty_view.xml
@@ -25,18 +25,20 @@
         android:layout_height="match_parent"
         android:gravity="center_horizontal">
 
-    <ProgressBar android:id="@+id/progress"
-                 android:layout_width="wrap_content"
-                 android:layout_height="wrap_content"
-                 android:layout_centerVertical="true"/>
+    <ProgressBar
+        android:id="@+id/progress"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"/>
+
     <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/progress"
-            android:layout_centerVertical="true"
-            android:text="@string/wait_for_sync_title"
-            android:textColor="@android:color/white"
-            android:textAppearance="?android:attr/textAppearanceMedium"/>
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/progress"
+        android:layout_centerVertical="true"
+        android:text="@string/wait_for_sync_title"
+        android:textColor="@color/dark_gray_text_color"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
 </RelativeLayout>
 
 
diff --git a/res/layout/one_pane_activity.xml b/res/layout/one_pane_activity.xml
index b236819..cb33b57 100644
--- a/res/layout/one_pane_activity.xml
+++ b/res/layout/one_pane_activity.xml
@@ -41,7 +41,7 @@
     <!--A drawer for phones: a pull-out that gives the list of folders. -->
     <fragment class="com.android.mail.ui.DrawerFragment"
         android:id="@+id/drawer_pullout"
-        android:layout_width="300dp"
+        android:layout_width="@dimen/drawer_width"
         android:layout_height="match_parent"
         android:layout_gravity="start" />
 
diff --git a/res/layout/two_pane_activity.xml b/res/layout/two_pane_activity.xml
index 18a4f66..03b2734 100644
--- a/res/layout/two_pane_activity.xml
+++ b/res/layout/two_pane_activity.xml
@@ -15,41 +15,46 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.mail.ui.TwoPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/two_pane_activity"
-    android:orientation="horizontal"
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/drawer_container"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <FrameLayout
-        android:id="@+id/content_pane"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:background="@drawable/drawer_shadow_tablet">
-        <fragment class="com.android.mail.ui.DrawerFragment"
-                  android:id="@+id/drawer_fragment"
-                  android:layout_height="match_parent"
-                  android:layout_width="match_parent"
-                />
+    <!-- DrawerLayout current only supports one content view (b/8752191) -->
+    <com.android.mail.ui.TwoPaneLayout
+        android:id="@+id/two_pane_activity"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <FrameLayout
+            android:id="@+id/content_pane"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:background="@drawable/drawer_shadow_tablet">
+            <fragment class="com.android.mail.ui.DrawerFragment"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
         </FrameLayout>
 
-    <FrameLayout
-        android:id="@+id/conversation_list_pane"
-        android:layout_width="0dp"
-        android:layout_height="match_parent" />
+        <FrameLayout
+            android:id="@+id/conversation_list_pane"
+            android:layout_width="0dp"
+            android:layout_height="match_parent" />
 
-    <com.android.mail.ui.ConversationListCopy
-        android:id="@+id/conversation_list_copy"
-        android:layout_width="0dp"
-        android:layout_height="match_parent" />
+        <com.android.mail.ui.ConversationListCopy
+            android:id="@+id/conversation_list_copy"
+            android:layout_width="0dp"
+            android:layout_height="match_parent" />
 
-    <include layout="@layout/conversation_pager"
-        android:id="@+id/conversation_pane"
-        android:layout_width="0dp"
-        android:layout_height="match_parent" />
+        <include layout="@layout/conversation_pager"
+            android:id="@+id/conversation_pane"
+            android:layout_width="0dp"
+            android:layout_height="match_parent" />
 
-    <com.android.mail.ui.ActionableToastBar
-        android:id="@+id/toast_bar"
-        style="@style/ToastBarStyle" />
+        <com.android.mail.ui.ActionableToastBar
+            android:id="@+id/toast_bar"
+            style="@style/ToastBarStyle" />
 
-</com.android.mail.ui.TwoPaneLayout>
+    </com.android.mail.ui.TwoPaneLayout>
+
+</android.support.v4.widget.DrawerLayout>
diff --git a/res/layout/widget.xml b/res/layout/widget.xml
index 128f45a..aebc6c9 100644
--- a/res/layout/widget.xml
+++ b/res/layout/widget.xml
@@ -79,13 +79,6 @@
             android:layout_gravity="center_vertical"
             android:contentDescription="@string/compose" />
     </LinearLayout>
-    <ListView
-        android:id="@+id/conversation_list"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-        android:cacheColorHint="#00000000"
-        android:background="@drawable/gradient_bg_widget_holo" />
     <LinearLayout
         android:id="@+id/widget_configuration"
         android:layout_width="match_parent"
@@ -107,6 +100,13 @@
             android:textSize="16sp"
             android:textStyle="bold"/>
     </LinearLayout>
+    <ListView
+        android:id="@+id/conversation_list"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:cacheColorHint="#00000000"
+        android:background="@drawable/gradient_bg_widget_holo" />
     <TextView
         android:id="@+id/empty_conversation_list"
         android:layout_width="match_parent"
diff --git a/res/menu-sw600dp/conversation_list_menu.xml b/res/menu-sw600dp/conversation_list_menu.xml
index ef35f84..4a69777 100644
--- a/res/menu-sw600dp/conversation_list_menu.xml
+++ b/res/menu-sw600dp/conversation_list_menu.xml
@@ -34,7 +34,7 @@
 
     <item android:id="@+id/refresh"
         android:title="@string/refresh"
-        android:showAsAction="ifRoom"
+        android:showAsAction="never"
         android:icon="@drawable/ic_menu_refresh_holo_light"
         android:alphabeticShortcut="@string/trigger_refresh_char" />
 
diff --git a/res/values-sw600dp-land/constants.xml b/res/values-sw600dp-land/constants.xml
index 66d7f72..ddddcae 100644
--- a/res/values-sw600dp-land/constants.xml
+++ b/res/values-sw600dp-land/constants.xml
@@ -15,8 +15,6 @@
      limitations under the License.
 -->
 <resources>
-    <integer name="conversation_list_weight">3</integer>
-    <integer name="conversation_view_weight">5</integer>
     <!-- Whether to show conversation subject in conversation view -->
     <bool name="show_conversation_subject">false</bool>
 
diff --git a/res/values-sw600dp/constants.xml b/res/values-sw600dp/constants.xml
index e625602..b41b7fa 100644
--- a/res/values-sw600dp/constants.xml
+++ b/res/values-sw600dp/constants.xml
@@ -18,12 +18,10 @@
 <resources>
     <!-- Boolean value indicating whether the table UI should be used. -->
     <integer name="use_tablet_ui">1</integer>
+    <bool name="use_expansive_tablet_ui">false</bool>
     <!-- Boolean value indicating whether conversation can be collapsed. -->
     <integer name="conversation_list_collapsible">1</integer>
     <integer name="conversation_header_mode">1</integer>
-    <integer name="folder_list_weight">1</integer>
-    <integer name="conversation_list_weight">2</integer>
-    <integer name="conversation_view_weight">3</integer>
     <integer name="conversation_desired_font_size_px">16</integer>
 
     <!-- Whether the list is collapsed in conversation view mode -->
diff --git a/res/values-sw720dp/constants.xml b/res/values-sw720dp/constants.xml
index 2ea59b7..c1b1315 100644
--- a/res/values-sw720dp/constants.xml
+++ b/res/values-sw720dp/constants.xml
@@ -16,11 +16,9 @@
      limitations under the License.
 -->
 <resources>
-    <integer name="folder_list_weight">1</integer>
-    <integer name="conversation_list_weight">3</integer>
-    <integer name="conversation_view_weight">6</integer>
     <!-- Whether the list is collapsed in conversation view mode -->
     <bool name="list_collapsed">true</bool>
+    <bool name="use_expansive_tablet_ui">true</bool>
 
     <!-- Search results in portrait mode on 10" tablets should still show wide conversation
          list items.
diff --git a/res/values-w1000dp/constants.xml b/res/values-w1000dp/constants.xml
index 35093e2..7fff7ff 100644
--- a/res/values-w1000dp/constants.xml
+++ b/res/values-w1000dp/constants.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2011 Google Inc.
+     Copyright (C) 2013 Google Inc.
      Licensed to The Android Open Source Project.
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,4 +18,7 @@
 <resources>
     <integer name="conversation_list_header_mode">0</integer>
     <integer name="conversation_list_search_header_mode">0</integer>
+    <integer name="folder_list_weight">1</integer>
+    <integer name="conversation_list_weight">3</integer>
+    <integer name="conversation_view_weight">6</integer>
 </resources>
\ No newline at end of file
diff --git a/res/values-w720dp/constants.xml b/res/values-w720dp/constants.xml
new file mode 100644
index 0000000..0806c41
--- /dev/null
+++ b/res/values-w720dp/constants.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 Google Inc.
+     Licensed to The Android Open Source Project.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <integer name="conversation_list_header_mode">0</integer>
+    <integer name="conversation_list_search_header_mode">0</integer>
+    <integer name="folder_list_weight">9</integer>
+    <integer name="conversation_list_weight">15</integer>
+    <integer name="conversation_view_weight">25</integer>
+</resources>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 8cff43d..10f7ce7 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -40,7 +40,6 @@
     <color name="default_folder_foreground_color">@color/gray_text_color</color>
 
     <!-- Folder List/Drawer colors -->
-    <color name="drawer_background_dim">#66000000</color>
     <color name="account_item_selected_text_color">#35b4e3</color>
     <color name="folder_list_divider_color">@color/gray_text_color</color>
     <color name="folder_list_heading_text_color">@color/dark_gray_text_color</color>
diff --git a/res/values/dimen.xml b/res/values/dimen.xml
index cf54a9c..3bff4f9 100644
--- a/res/values/dimen.xml
+++ b/res/values/dimen.xml
@@ -17,6 +17,9 @@
 -->
 
 <resources>
+    <dimen name="drawer_width">300dp</dimen>
+    <dimen name="list_min_width_is_wide">720dp</dimen>
+    <dimen name="list_normal_mode_min_width_is_spacious">600dp</dimen>
     <dimen name="account_dropdown_item_height">48dip</dimen>
     <dimen name="senders_font_size">18sp</dimen>
     <dimen name="subject_font_size">14sp</dimen>
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index 5c562a7..e62a97c 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -158,7 +158,6 @@
     private int mViewWidth = -1;
     /** The view mode at which we calculated mViewWidth previously. */
     private int mPreviousMode;
-    private int mMode = -1;
     private int mDateX;
     private int mPaperclipX;
     private int mSendersWidth;
@@ -242,7 +241,7 @@
             return mFoldersCount > 0;
         }
 
-        private int measureFolders(int mode, int availableSpace, int cellSize) {
+        private int measureFolders(int availableSpace, int cellSize) {
             int totalWidth = 0;
             boolean firstTime = true;
             for (Folder f : mFoldersSortedSet) {
@@ -262,8 +261,7 @@
             return totalWidth;
         }
 
-        public void drawFolders(Canvas canvas, ConversationItemViewCoordinates coordinates,
-                int mode) {
+        public void drawFolders(Canvas canvas, ConversationItemViewCoordinates coordinates) {
             if (mFoldersCount == 0) {
                 return;
             }
@@ -280,12 +278,12 @@
             // Initialize space and cell size based on the current mode.
             int availableSpace = xEnd - xMinStart;
             int averageWidth = availableSpace / mFoldersCount;
-            int cellSize = ConversationItemViewCoordinates.getFolderCellWidth(mContext);
+            int cellSize = coordinates.getFolderCellWidth();
 
             // TODO(ath): sFoldersPaint.measureText() is done 3x in this method. stop that.
             // Extra credit: maybe cache results across items as long as font size doesn't change.
 
-            final int totalWidth = measureFolders(mode, availableSpace, cellSize);
+            final int totalWidth = measureFolders(availableSpace, cellSize);
             int xStart = xEnd - Math.min(availableSpace, totalWidth);
             final boolean overflow = totalWidth > availableSpace;
 
@@ -600,15 +598,6 @@
         return mHeader.conversation;
     }
 
-    /**
-     * Sets the mode. Only used for testing.
-     */
-    @VisibleForTesting
-    void setMode(int mode) {
-        mMode = mode;
-        mTesting = true;
-    }
-
     private static void startTimer(String tag) {
         if (sTimer != null) {
             sTimer.start(tag);
@@ -629,13 +618,10 @@
         if (wSize != mViewWidth || mPreviousMode != currentMode) {
             mViewWidth = wSize;
             mPreviousMode = currentMode;
-            if (!mTesting) {
-                mMode = ConversationItemViewCoordinates.getMode(mContext, mPreviousMode);
-            }
         }
         mHeader.viewWidth = mViewWidth;
 
-        mConfig.updateWidth(wSize).setMode(mMode);
+        mConfig.updateWidth(wSize).setViewMode(currentMode);
 
         Resources res = getResources();
         mHeader.standardScaledDimen = res.getDimensionPixelOffset(R.dimen.standard_scaled_dimen);
@@ -718,8 +704,7 @@
             mHeader.messageInfoString = SendersView
                     .createMessageInfo(context, mHeader.conversation, true);
             int maxChars = ConversationItemViewCoordinates.getSendersLength(context,
-                    ConversationItemViewCoordinates.getMode(context, mActivity.getViewMode()),
-                    mHeader.conversation.hasAttachments);
+                    mCoordinates.getMode(), mHeader.conversation.hasAttachments);
             mHeader.displayableSenderEmails = new ArrayList<String>();
             mHeader.displayableSenderNames = new ArrayList<String>();
             mHeader.styledSenders = new ArrayList<SpannableString>();
@@ -776,7 +761,8 @@
             if (mCoordinates.contactImagesWidth <= 0 || mCoordinates.contactImagesHeight <= 0) {
                 LogUtils.w(LOG_TAG,
                         "Contact image width(%d) or height(%d) is 0 for mode: (%d).",
-                        mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight, mMode);
+                        mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight,
+                        mCoordinates.getMode());
                 return;
             }
             mContactImagesHolder.setDimensions(mCoordinates.contactImagesWidth,
@@ -801,8 +787,8 @@
             if (mCoordinates.attachmentPreviewsWidth <= 0 || attachmentPreviewsHeight <= 0) {
                 LogUtils.w(LOG_TAG,
                         "Attachment preview width(%d) or height(%d) is 0 for mode: (%d,%d).",
-                        mCoordinates.attachmentPreviewsWidth, attachmentPreviewsHeight, mMode,
-                        mAttachmentPreviewMode);
+                        mCoordinates.attachmentPreviewsWidth, attachmentPreviewsHeight,
+                        mCoordinates.getMode(), mAttachmentPreviewMode);
                 return;
             }
             mAttachmentPreviewsCanvas.setDimensions(mCoordinates.attachmentPreviewsWidth,
@@ -920,7 +906,7 @@
 
         mPaperclipX = mDateX - ATTACHMENT.getWidth() - mCoordinates.datePaddingLeft;
 
-        if (mConfig.isWide()) {
+        if (mCoordinates.isWide()) {
             // In wide mode, the end of the senders should align with
             // the start of the subject and is based on a max width.
             mSendersWidth = mCoordinates.sendersWidth;
@@ -961,7 +947,7 @@
                 totalWidth += senderFragment.width;
             }
 
-            if (!ConversationItemViewCoordinates.displaySendersInline(mMode)) {
+            if (!ConversationItemViewCoordinates.displaySendersInline(mCoordinates.getMode())) {
                 sendersY += totalWidth <= mSendersWidth ? mCoordinates.sendersLineHeight / 2 : 0;
             }
             if (mSendersWidth < 0) {
@@ -1200,7 +1186,7 @@
 
         // Folders.
         if (mConfig.areFoldersVisible()) {
-            mHeader.folderDisplayer.drawFolders(canvas, mCoordinates, mMode);
+            mHeader.folderDisplayer.drawFolders(canvas, mCoordinates);
         }
 
         // If this folder has a color (combined view/Email), show it here
diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
index 50fb778..bab9711 100644
--- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java
+++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
@@ -72,7 +72,7 @@
      */
     public static final class Config {
         private int mWidth;
-        private int mMode = NORMAL_MODE;
+        private int mViewMode = ViewMode.UNKNOWN;
         private int mGadgetMode = GADGET_NONE;
         private int mAttachmentPreviewMode = ATTACHMENT_PREVIEW_NONE;
         private boolean mShowFolders = false;
@@ -80,8 +80,8 @@
         private boolean mShowColorBlock = false;
         private boolean mShowPersonalIndicator = false;
 
-        public Config setMode(int mode) {
-            mMode = mode;
+        public Config setViewMode(int viewMode) {
+            mViewMode = viewMode;
             return this;
         }
 
@@ -124,12 +124,8 @@
             return mWidth;
         }
 
-        public int getMode() {
-            return mMode;
-        }
-
-        public boolean isWide() {
-            return mMode == WIDE_MODE;
+        public int getViewMode() {
+            return mViewMode;
         }
 
         public int getGadgetMode() {
@@ -158,12 +154,17 @@
 
         private int getCacheKey() {
             // hash the attributes that contribute to item height and child view geometry
-            return Objects.hashCode(mWidth, mMode, mGadgetMode, mAttachmentPreviewMode,
+            return Objects.hashCode(mWidth, mViewMode, mGadgetMode, mAttachmentPreviewMode,
                     mShowFolders, mShowReplyState, mShowPersonalIndicator);
         }
 
     }
 
+    /**
+     * One of either NORMAL_MODE or WIDE_MODE.
+     */
+    private final int mMode;
+
     final int height;
 
     // Attachments view
@@ -240,10 +241,38 @@
     final int contactImagesX;
     final int contactImagesY;
 
+    /**
+     * The smallest item width for which we use the "wide" layout.
+     */
+    private final int mMinListWidthForWide;
+    /**
+     * The smallest item width for which we use the "spacious" variant of the normal layout,
+     * if the normal version is used at all. Larger than {@link #mMinListWidthForWide}, we use
+     * wide mode anyway, and this value is unused.
+     */
+    private final int mMinListWidthIsSpacious;
+    private final int mFolderCellWidth;
+
     private ConversationItemViewCoordinates(Context context, Config config) {
-        final ViewGroup view = (ViewGroup) LayoutInflater.from(context).inflate(
-                config.getMode() == WIDE_MODE ? R.layout.conversation_item_view_wide :
-                    R.layout.conversation_item_view_normal, null);
+        final Resources res = context.getResources();
+        mFolderCellWidth = res.getDimensionPixelSize(R.dimen.folder_cell_width);
+        mMinListWidthForWide = res.getDimensionPixelSize(R.dimen.list_min_width_is_wide);
+        mMinListWidthIsSpacious = res.getDimensionPixelSize(
+                R.dimen.list_normal_mode_min_width_is_spacious);
+
+        mMode = calculateMode(res, config);
+
+        final int layoutId;
+        if (mMode == WIDE_MODE) {
+            layoutId = R.layout.conversation_item_view_wide;
+        } else {
+            if (config.getWidth() >= mMinListWidthIsSpacious) {
+                layoutId = R.layout.conversation_item_view_normal_spacious;
+            } else {
+                layoutId = R.layout.conversation_item_view_normal;
+            }
+        }
+        final ViewGroup view = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);
 
         final TextView folders = (TextView) view.findViewById(R.id.folders);
         folders.setVisibility(config.areFoldersVisible() ? View.VISIBLE : View.GONE);
@@ -293,7 +322,6 @@
         // Layout the appropriate view.
         final int widthSpec = MeasureSpec.makeMeasureSpec(config.getWidth(), MeasureSpec.EXACTLY);
         final int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-        final Resources res = context.getResources();
 
         view.measure(widthSpec, heightSpec);
         view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
@@ -336,7 +364,7 @@
         final TextView subject = (TextView) view.findViewById(R.id.subject);
         final int subjectTopAdjust = getLatinTopAdjustment(subject);
         subjectX = getX(subject);
-        if (config.isWide()) {
+        if (isWide()) {
             subjectY = getY(subject) + subjectTopAdjust;
         } else {
             subjectY = getY(subject) + sendersTopAdjust;
@@ -351,7 +379,7 @@
             // vertically align folders min left edge with subject
             foldersX = subjectX;
             foldersXEnd = getX(folders) + folders.getWidth();
-            if (config.isWide()) {
+            if (isWide()) {
                 foldersY = getY(folders);
             } else {
                 foldersY = getY(folders) + sendersTopAdjust;
@@ -419,7 +447,15 @@
             attachmentPreviewsWidth = 0;
         }
 
-        height = view.getHeight() + (config.isWide() ? 0 : sendersTopAdjust);
+        height = view.getHeight() + (isWide() ? 0 : sendersTopAdjust);
+    }
+
+    public int getMode() {
+        return mMode;
+    }
+
+    public boolean isWide() {
+        return mMode == WIDE_MODE;
     }
 
     /**
@@ -437,13 +473,12 @@
     }
 
     /**
-     * Returns the mode of the header view (Wide/Normal/Narrow).
+     * Returns the mode of the header view (Wide/Normal).
      */
-    public static int getMode(Context context, int viewMode) {
-        final Resources res = context.getResources();
-        switch (viewMode) {
+    private int calculateMode(Resources res, Config config) {
+        switch (config.getViewMode()) {
             case ViewMode.CONVERSATION_LIST:
-                return res.getInteger(R.integer.conversation_list_header_mode);
+                return config.getWidth() >= mMinListWidthForWide ? WIDE_MODE : NORMAL_MODE;
 
             case ViewMode.SEARCH_RESULTS_LIST:
                 return res.getInteger(R.integer.conversation_list_search_header_mode);
@@ -454,13 +489,6 @@
     }
 
     /**
-     * Returns the mode of the header view (Wide/Normal/Narrow).
-     */
-    public static int getMode(Context context, ViewMode viewMode) {
-        return getMode(context, viewMode.getMode());
-    }
-
-    /**
      * Returns a value array multiplied by the specified density.
      */
     public static int[] getDensityDependentArray(int[] values, float density) {
@@ -605,8 +633,8 @@
      * intra-cell margin within cells.
      *
      */
-    public static int getFolderCellWidth(Context context) {
-        return context.getResources().getDimensionPixelSize(R.dimen.folder_cell_width);
+    public int getFolderCellWidth() {
+        return mFolderCellWidth;
     }
 
     public static boolean isWideMode(int mode) {
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 4b418c5..22c635c 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -17,6 +17,7 @@
 
 package com.android.mail.ui;
 
+import android.animation.ValueAnimator;
 import android.app.ActionBar;
 import android.app.ActionBar.LayoutParams;
 import android.app.Activity;
@@ -44,7 +45,10 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.SearchRecentSuggestions;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
 import android.view.DragEvent;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -52,6 +56,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.widget.ListView;
 import android.widget.Toast;
 
 import com.android.mail.ConversationListContext;
@@ -336,6 +341,13 @@
 
     private final Deque<UpOrBackHandler> mUpOrBackHandlers = Lists.newLinkedList();
 
+    protected DrawerLayout mDrawerContainer;
+    protected View mDrawerPullout;
+    protected ActionBarDrawerToggle mDrawerToggle;
+    protected ListView mListViewForAnimating;
+    protected boolean mHasNewAccountOrFolder;
+    protected final MailDrawerListener mDrawerListener = new MailDrawerListener();
+
     public static final String SYNC_ERROR_DIALOG_FRAGMENT_TAG = "SyncErrorDialogFragment";
 
     private final DataSetObserver mUndoNotificationObserver = new DataSetObserver() {
@@ -461,10 +473,9 @@
                 isSearch ? R.layout.search_actionbar_view : R.layout.actionbar_view, null);
         mActionBarView.initialize(mActivity, this, actionBar);
 
-        //  If not a tablet, we always want the up/back button to show at top.
-        if(!mIsTablet) {
-            mActionBarView.setBackButton();
-        }
+        // init the action bar to allow the 'up' affordance.
+        // any configurations that disallow 'up' should do that later.
+        mActionBarView.setBackButton();
     }
 
     /**
@@ -624,12 +635,39 @@
     }
 
     /**
-     * The default behavior for drawer closed is to notify the observers as, by default, there
-     * is no drawer.
+     * If the drawer is open, the function locks the drawer to the closed, thereby sliding in
+     * the drawer to the left edge, disabling events, and refreshing it once it's either closed
+     * or put in an idle state.
      */
     @Override
     public void closeDrawer(final boolean hasNewFolderOrAccount) {
-        mDrawerObservers.notifyChanged();
+        if (!isDrawerEnabled()) {
+            mDrawerObservers.notifyChanged();
+            return;
+        }
+
+        // If there are no new folders or accounts to switch to, just close the drawer
+        if (!hasNewFolderOrAccount) {
+            mDrawerContainer.closeDrawers();
+            return;
+        }
+
+        final ConversationListFragment conversationList = getConversationListFragment();
+        if (conversationList != null) {
+            mListViewForAnimating = conversationList.getListView();
+        } else {
+            // There is no conversation list to animate, so just set it to null
+            mListViewForAnimating = null;
+        }
+
+        if (mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
+            // Lets the drawer listener update the drawer contents and notify the FolderListFragment
+            mHasNewAccountOrFolder = true;
+            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+        } else {
+            // Drawer is already closed, notify observers that is the case.
+            mDrawerObservers.notifyChanged();
+        }
     }
 
     private void fetchSearchFolder(Intent intent) {
@@ -641,6 +679,7 @@
 
     @Override
     public void onFolderChanged(Folder folder) {
+        mDrawerContainer.closeDrawers();
         changeFolder(folder, null);
     }
 
@@ -931,6 +970,14 @@
         mRecentFolderList.initialize(mActivity);
         mVeiledMatcher.initialize(this);
 
+        mDrawerToggle = new ActionBarDrawerToggle((Activity) mActivity, mDrawerContainer,
+                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
+        mDrawerContainer.setDrawerListener(new MailDrawerListener());
+        mDrawerContainer.setDrawerShadow(
+                mContext.getResources().getDrawable(R.drawable.drawer_shadow), Gravity.START);
+
+        mDrawerToggle.setDrawerIndicatorEnabled(isDrawerEnabled());
+
         // All the individual UI components listen for ViewMode changes. This
         // simplifies the amount of logic in the AbstractActivityController, but increases the
         // possibility of timing-related bugs.
@@ -970,12 +1017,25 @@
 
     @Override
     public void onPostCreate(Bundle savedState) {
-        // Do nothing
+        // Sync the toggle state after onRestoreInstanceState has occurred.
+        mDrawerToggle.syncState();
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        // Do nothing
+        mDrawerToggle.onConfigurationChanged(newConfig);
+    }
+
+    /**
+     * If drawer is open/visible (even partially), close it.
+     */
+    protected void closeDrawerIfOpen() {
+        if (!isDrawerEnabled()) {
+            return;
+        }
+        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
+            mDrawerContainer.closeDrawers();
+        }
     }
 
     @Override
@@ -1023,6 +1083,14 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        /*
+         * The action bar home/up action should open or close the drawer.
+         * mDrawerToggle will take care of this.
+         */
+        if (mDrawerToggle.onOptionsItemSelected(item)) {
+            return true;
+        }
+
         final int id = item.getItemId();
         LogUtils.d(LOG_TAG, "AbstractController.onOptionsItemSelected(%d) called.", id);
         boolean handled = true;
@@ -1141,11 +1209,20 @@
     }
 
     /**
-     * Stand-in method overriden in OnePaneController for toggling the state
-     * of the drawer.
+     * Toggles the drawer pullout. If it was open (Fully extended), the
+     * drawer will be closed. Otherwise, the drawer will be opened. This should
+     * only be called when used with a toggle item. Other cases should be handled
+     * explicitly with just closeDrawers() or openDrawer(View drawerView);
      */
     protected void toggleFolderListState() {
-        //Implemented in OnePaneController.java
+        if (!isDrawerEnabled()) {
+            return;
+        }
+        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
+            mDrawerContainer.closeDrawers();
+        } else {
+            mDrawerContainer.openDrawer(mDrawerPullout);
+        }
     }
 
     @Override
@@ -1165,6 +1242,12 @@
                 return true;
             }
         }
+
+        if (isDrawerEnabled() && mDrawerContainer.isDrawerVisible(mDrawerPullout)) {
+            mDrawerContainer.closeDrawers();
+            return true;
+        }
+
         return handleBackPress();
     }
 
@@ -1502,6 +1585,7 @@
         }.run(mResolver, msg.uri, values, null /* selection*/, null /* selectionArgs */);
     }
 
+    @Override
     public void requestFolderRefresh() {
         if (mFolder == null) {
             return;
@@ -1719,6 +1803,28 @@
         if (newMode != ViewMode.UNKNOWN) {
             resetActionBarIcon();
         }
+
+        if (isDrawerEnabled()) {
+            // if search list/conv mode, disable drawer pull and indicator
+            // allow drawer pull everywhere except conversation mode where the list is hidden
+            // only allow indicator at top level of app
+            final boolean showIndicator;
+            final boolean allowPull;
+            if (ViewMode.isSearchMode(newMode)) {
+                showIndicator = false;
+                allowPull = false;
+            } else {
+                allowPull = !(ViewMode.isConversationMode(newMode)
+                        // TODO(ath): get this to work to allow drawer pull in 2-pane conv mode.
+                        /* && !isConversationListVisible() */);
+                showIndicator = (newMode == ViewMode.CONVERSATION_LIST
+                        || newMode == ViewMode.FOLDER_LIST);
+            }
+            mDrawerToggle.setDrawerIndicatorEnabled(showIndicator);
+            mDrawerContainer.setDrawerLockMode(allowPull ? DrawerLayout.LOCK_MODE_UNLOCKED :
+                DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+            closeDrawerIfOpen();
+        }
     }
 
     public void disablePagerUpdates() {
@@ -3628,4 +3734,61 @@
         }
         mDetachedConvUri = null;
     }
+
+    private class MailDrawerListener implements DrawerLayout.DrawerListener {
+        @Override
+        public void onDrawerOpened(View drawerView) {
+            mDrawerToggle.onDrawerOpened(drawerView);
+        }
+
+        @Override
+        public void onDrawerClosed(View drawerView) {
+            mDrawerToggle.onDrawerClosed(drawerView);
+            if (mHasNewAccountOrFolder) {
+                refreshDrawer();
+            }
+        }
+
+        /**
+         * As part of the overriden function, it will animate the alpha of the conversation list
+         * view along with the drawer sliding when we're in the process of switching accounts or
+         * folders. Note, this is the same amount of work done as {@link ValueAnimator#ofFloat}.
+         */
+        @Override
+        public void onDrawerSlide(View drawerView, float slideOffset) {
+            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
+            if (mHasNewAccountOrFolder && mListViewForAnimating != null) {
+                mListViewForAnimating.setAlpha(slideOffset);
+            }
+        }
+
+        /**
+         * This condition here should only be called when the drawer is stuck in a weird state
+         * and doesn't register the onDrawerClosed, but shows up as idle. Make sure to refresh
+         * and, more importantly, unlock the drawer when this is the case.
+         */
+        @Override
+        public void onDrawerStateChanged(int newState) {
+            mDrawerToggle.onDrawerStateChanged(newState);
+            if (mHasNewAccountOrFolder && newState == DrawerLayout.STATE_IDLE) {
+                refreshDrawer();
+            }
+        }
+
+        /**
+         * If we've reached a stable drawer state, unlock the drawer for usage, clear the
+         * conversation list, and finish end actions. Also, make
+         * {@link #mHasNewAccountOrFolder} false to reflect we're done changing.
+         */
+        public void refreshDrawer() {
+            mHasNewAccountOrFolder = false;
+            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
+            ConversationListFragment conversationList = getConversationListFragment();
+            if (conversationList != null) {
+                conversationList.clear();
+            }
+            mDrawerObservers.notifyChanged();
+        }
+    }
+
 }
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 272e129..38b944d 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -551,7 +551,7 @@
     }
 
     public void setBackButton() {
-        if (mActionBar == null){
+        if (mActionBar == null) {
             return;
         }
         // Show home as up, and show an icon.
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index 804317b..527513a 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -17,22 +17,13 @@
 
 package com.android.mail.ui;
 
-import android.animation.ValueAnimator;
-import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.app.LoaderManager.LoaderCallbacks;
-import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.widget.DrawerLayout;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.widget.ListView;
 
 import com.android.mail.ConversationListContext;
 import com.android.mail.R;
@@ -75,70 +66,6 @@
     private Folder mInbox;
     /** Whether a conversation list for this account has ever been shown.*/
     private boolean mConversationListNeverShown = true;
-    private boolean mHasNewAccountOrFolder = false;
-    private DrawerLayout mDrawerContainer;
-    private ViewGroup mDrawerPullout;
-    private ListView mListViewForAnimating;
-
-    private ActionBarDrawerToggle mDrawerToggle;
-
-    private class MailDrawerListener implements DrawerLayout.DrawerListener {
-        @Override
-        public void onDrawerOpened(View drawerView) {
-            mDrawerToggle.onDrawerOpened(drawerView);
-        }
-
-        @Override
-        public void onDrawerClosed(View drawerView) {
-            mDrawerToggle.onDrawerClosed(drawerView);
-            if (mHasNewAccountOrFolder) {
-                refreshDrawer();
-            }
-        }
-
-        /**
-         * As part of the overriden function, it will animate the alpha of the conversation list
-         * view along with the drawer sliding when we're in the process of switching accounts or
-         * folders. Note, this is the same amount of work done as {@link ValueAnimator#ofFloat}.
-         */
-        @Override
-        public void onDrawerSlide(View drawerView, float slideOffset) {
-            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
-            if (mHasNewAccountOrFolder && mListViewForAnimating != null) {
-                mListViewForAnimating.setAlpha(slideOffset);
-                LogUtils.w(LOG_TAG, "OFFSET: " + slideOffset);
-            }
-        }
-
-        /**
-         * This condition here should only be called when the drawer is stuck in a weird state
-         * and doesn't register the onDrawerClosed, but shows up as idle. Make sure to refresh
-         * and, more importantly, unlock the drawer when this is the case.
-         */
-        @Override
-        public void onDrawerStateChanged(int newState) {
-            mDrawerToggle.onDrawerStateChanged(newState);
-            if (mHasNewAccountOrFolder && newState == DrawerLayout.STATE_IDLE) {
-                refreshDrawer();
-            }
-        }
-
-        /**
-         * If we've reached a stable drawer state, unlock the drawer for usage, clear the
-         * conversation list, and finish end actions. Also, make
-         * {@link OnePaneController#mHasNewAccountOrFolder} false to reflect we're done changing.
-         */
-        public void refreshDrawer() {
-            mHasNewAccountOrFolder = false;
-            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
-            ConversationListFragment conversationList = getConversationListFragment();
-            if (conversationList != null) {
-                conversationList.clear();
-            }
-            notifyDrawerClosed();
-        }
-    }
-
 
     public OnePaneController(MailActivity activity, ViewMode viewMode) {
         super(activity, viewMode);
@@ -219,77 +146,22 @@
     public boolean onCreate(Bundle savedInstanceState) {
         mActivity.setContentView(R.layout.one_pane_activity);
         mDrawerContainer = (DrawerLayout) mActivity.findViewById(R.id.drawer_container);
-        mDrawerContainer.setScrimColor(
-                mContext.getResources().getColor(R.color.drawer_background_dim));
-        mDrawerContainer.setDrawerListener(new MailDrawerListener());
-        mDrawerPullout = (ViewGroup) mDrawerContainer.findViewById(R.id.drawer_pullout);
-        mDrawerContainer.setDrawerShadow(
-                mContext.getResources().getDrawable(R.drawable.drawer_shadow), Gravity.LEFT);
+        mDrawerPullout = mDrawerContainer.findViewById(R.id.drawer_pullout);
         mDrawerPullout.setBackgroundResource(R.color.list_background_color);
 
-        mDrawerToggle = new ActionBarDrawerToggle((Activity)mActivity, mDrawerContainer,
-                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
-
         // The parent class sets the correct viewmode and starts the application off.
         return super.onCreate(savedInstanceState);
     }
 
     @Override
-    public void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-
-        // Sync the toggle state after onRestoreInstanceState has occurred.
-        mDrawerToggle.syncState();
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        /*
-         * The action bar home/up action should open or close the drawer.
-         * mDrawerToggle will take care of this.
-         */
-        if (mDrawerToggle.onOptionsItemSelected(item)) {
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mDrawerToggle.onConfigurationChanged(newConfig);
-    }
-
-    @Override
     protected boolean isConversationListVisible() {
         return mConversationListVisible;
     }
 
-    /**
-     * If drawer is open/visible (even partially), close it.
-     */
-    private void closeDrawerIfOpen() {
-        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
-            mDrawerContainer.closeDrawers();
-        }
-    }
-
     @Override
     public void onViewModeChanged(int newMode) {
         super.onViewModeChanged(newMode);
 
-        // When view mode changes, lock drawer if viewing search results or
-        // viewing a conversation. Set unlocked otherwise.
-        if (ViewMode.isSearchMode(newMode) || ViewMode.isConversationMode(newMode)) {
-            mDrawerToggle.setDrawerIndicatorEnabled(false);
-            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-        } else {
-            mDrawerToggle.setDrawerIndicatorEnabled(true);
-            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
-        }
-        closeDrawerIfOpen();
-
         // When entering conversation list mode, hide and clean up any currently visible
         // conversation.
         if (ViewMode.isListMode(newMode)) {
@@ -319,6 +191,7 @@
     public void showConversationList(ConversationListContext listContext) {
         super.showConversationList(listContext);
         enableCabMode();
+        mConversationListVisible = true;
         if (ConversationListContext.isSearchResult(listContext)) {
             mViewMode.enterSearchResultsListMode();
         } else {
@@ -352,7 +225,6 @@
 
         mActivity.getFragmentManager().executePendingTransactions();
 
-        mConversationListVisible = true;
         onConversationVisibilityChanged(false);
         onConversationListVisibilityChanged(true);
         mConversationListNeverShown = false;
@@ -361,6 +233,7 @@
     @Override
     protected void showConversation(Conversation conversation, boolean inLoaderCallbacks) {
         super.showConversation(conversation, inLoaderCallbacks);
+        mConversationListVisible = false;
         if (conversation == null) {
             transitionBackToConversationListMode(inLoaderCallbacks);
             return;
@@ -392,7 +265,6 @@
         }
         mPagerController.show(mAccount, mFolder, conversation, true /* changeVisibility */);
         onConversationVisibilityChanged(true);
-        mConversationListVisible = false;
         onConversationListVisibilityChanged(false);
     }
 
@@ -431,27 +303,6 @@
     }
 
     /**
-     * Toggles the drawer pullout. If it was open (Fully extended), the
-     * drawer will be closed. Otherwise, the drawer will be opened. This should
-     * only be called when used with a toggle item. Other cases should be handled
-     * explicitly with just closeDrawers() or openDrawer(View drawerView);
-     */
-    @Override
-    protected void toggleFolderListState() {
-        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
-            mDrawerContainer.closeDrawers();
-        } else {
-            mDrawerContainer.openDrawer(mDrawerPullout);
-        }
-    }
-
-    @Override
-    public void onFolderChanged(Folder folder) {
-        mDrawerContainer.closeDrawers();
-        super.onFolderChanged(folder);
-    }
-
-    /**
      * Replace the content_pane with the fragment specified here. The tag is specified so that
      * the {@link ActivityController} can look up the fragments through the
      * {@link android.app.FragmentManager}. This action will be placed on the back stack.
@@ -502,11 +353,6 @@
     public boolean handleBackPress() {
         final int mode = mViewMode.getMode();
 
-        if (mDrawerContainer.isDrawerVisible(mDrawerPullout)) {
-            mDrawerContainer.closeDrawers();
-            return true;
-        }
-
         //TODO(shahrk): Remove the folder list standalone view
         if (mode == ViewMode.FOLDER_LIST) {
             final Folder hierarchyFolder = getHierarchyFolder();
@@ -645,6 +491,7 @@
     private void transitionBackToConversationListMode(boolean inLoaderCallbacks) {
         final int mode = mViewMode.getMode();
         enableCabMode();
+        mConversationListVisible = true;
         if (mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
             mViewMode.enterSearchResultsListMode();
         } else {
@@ -660,7 +507,6 @@
             // Set the correct context for what the conversation view will be now.
             onFolderChanged(mInbox);
         }
-        mConversationListVisible = true;
         onConversationVisibilityChanged(false);
         onConversationListVisibilityChanged(true);
     }
@@ -801,46 +647,6 @@
         }
     }
 
-    /**
-     * The default behavior calls mDrawerObserver's notifyChanged(). So, to notify the consumer of
-     * the observer that the drawer is closed, we simply make a call to
-     * {@link AbstractActivityController#closeDrawer(boolean)}.
-     */
-    public void notifyDrawerClosed() {
-        super.closeDrawer(true);
-    }
-
-    /**
-     * If the drawer is open, the function locks the drawer to the closed, thereby sliding in
-     * the drawer to the left edge, disabling events, and refreshing it once it's either closed
-     * or put in an idle state.
-     */
-    @Override
-    public void closeDrawer(final boolean hasNewFolderOrAccount) {
-        // If there are no new folders or accounts to switch to, just close the drawer
-        if (!hasNewFolderOrAccount) {
-            mDrawerContainer.closeDrawers();
-            return;
-        }
-
-        final ConversationListFragment conversationList = getConversationListFragment();
-        if (conversationList != null) {
-            mListViewForAnimating = conversationList.getListView();
-        } else {
-            // There is no conversation list to animate, so just set it to null
-            mListViewForAnimating = null;
-        }
-
-        if (mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
-            // Lets the drawer listener update the drawer contents and notify the FolderListFragment
-            mHasNewAccountOrFolder = true;
-            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-        } else {
-            // Drawer is already closed, notify observers that is the case.
-            notifyDrawerClosed();
-        }
-    }
-
     @Override
     public boolean isDrawerEnabled() {
         // The drawer is enabled for one pane mode
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 67bbbd5..2a04877 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -21,6 +21,7 @@
 import android.app.FragmentTransaction;
 import android.content.Intent;
 import android.os.Bundle;
+import android.support.v4.widget.DrawerLayout;
 import android.view.Gravity;
 import android.widget.FrameLayout;
 
@@ -127,12 +128,15 @@
     @Override
     public boolean onCreate(Bundle savedState) {
         mActivity.setContentView(R.layout.two_pane_activity);
+        mDrawerContainer = (DrawerLayout) mActivity.findViewById(R.id.drawer_container);
+        mDrawerPullout = mDrawerContainer.findViewById(R.id.content_pane);
         mLayout = (TwoPaneLayout) mActivity.findViewById(R.id.two_pane_activity);
         if (mLayout == null) {
             // We need the layout for everything. Crash early if it is null.
             LogUtils.wtf(LOG_TAG, "mLayout is null!");
         }
         mLayout.setController(this, Intent.ACTION_SEARCH.equals(mActivity.getIntent().getAction()));
+        mLayout.setDrawerLayout(mDrawerContainer);
 
         // 2-pane layout is the main listener of view mode changes, and issues secondary
         // notifications upon animation completion:
@@ -218,6 +222,9 @@
 
     @Override
     public void resetActionBarIcon() {
+        if (isDrawerEnabled()) {
+            return;
+        }
         // On two-pane, the back button is only removed in the conversation list mode, and shown
         // for every other condition.
         if (mViewMode.isListMode() || mViewMode.isWaitingForSync()) {
@@ -577,7 +584,6 @@
 
     @Override
     public boolean isDrawerEnabled() {
-        // The drawer is currently not enabled for two pane mode
-        return false;
+        return mLayout.isDrawerEnabled();
     }
 }
diff --git a/src/com/android/mail/ui/TwoPaneLayout.java b/src/com/android/mail/ui/TwoPaneLayout.java
index 2164be4..011df72 100644
--- a/src/com/android/mail/ui/TwoPaneLayout.java
+++ b/src/com/android/mail/ui/TwoPaneLayout.java
@@ -23,9 +23,12 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.support.v4.widget.DrawerLayout;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
 
@@ -86,6 +89,8 @@
     private LayoutListener mListener;
     private boolean mIsSearchResult;
 
+    private DrawerLayout mDrawerLayout;
+
     private View mConversationView;
     private View mFoldersView;
     private View mListView;
@@ -106,6 +111,8 @@
      */
     private Integer mListCopyWidthOnComplete;
 
+    private final boolean mIsExpansiveLayout;
+
     public TwoPaneLayout(Context context) {
         this(context, null);
     }
@@ -130,6 +137,8 @@
                 / (folderListWeight + convListWeight);
         mConversationListWeight = (double) convListWeight
                 / (convListWeight + convViewWeight);
+
+        mIsExpansiveLayout = res.getBoolean(R.bool.use_expansive_tablet_ui);
     }
 
     @Override
@@ -156,6 +165,10 @@
         mIsSearchResult = isSearchResult;
     }
 
+    public void setDrawerLayout(DrawerLayout drawerLayout) {
+        mDrawerLayout = drawerLayout;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         LogUtils.d(Utils.VIEW_DEBUGGING_TAG, "TPL(%s).onMeasure()", this);
@@ -180,14 +193,21 @@
      */
     private void setupPaneWidths(int parentWidth) {
         final int foldersWidth = computeFolderListWidth(parentWidth);
+        final int foldersFragmentWidth;
+        if (isDrawerView(mFoldersView)) {
+            foldersFragmentWidth = getResources().getDimensionPixelSize(R.dimen.drawer_width);
+        } else {
+            foldersFragmentWidth = foldersWidth;
+        }
         final int convWidth = computeConversationWidth(parentWidth);
 
-        // only adjust the fixed folder and conversation view widths when my width changes
+        setPaneWidth(mFoldersView, foldersFragmentWidth);
+
+        // only adjust the fixed conversation view width when my width changes
         if (parentWidth != getMeasuredWidth()) {
             LogUtils.i(LOG_TAG, "setting up new TPL, w=%d fw=%d cv=%d", parentWidth,
                     foldersWidth, convWidth);
 
-            setPaneWidth(mFoldersView, foldersWidth);
             setPaneWidth(mConversationView, convWidth);
         }
 
@@ -286,8 +306,10 @@
         // a view intent.
         if (mPositionedMode == ViewMode.UNKNOWN) {
             mConversationView.setX(convX);
-            mFoldersView.setX(foldersX);
             mListView.setX(listX);
+            if (!isDrawerView(mFoldersView)) {
+                mFoldersView.setX(foldersX);
+            }
 
             // listeners need to know that the "transition" is complete, even if one is not run.
             // defer notifying listeners because we're in a layout pass, and they might do layout.
@@ -310,7 +332,9 @@
         useHardwareLayer(true);
 
         mConversationView.animate().x(convX);
-        mFoldersView.animate().x(foldersX);
+        if (!isDrawerView(mFoldersView)) {
+            mFoldersView.animate().x(foldersX);
+        }
         mListCopyView.animate().x(listX).alpha(0.0f);
         mListView.animate()
             .x(listX)
@@ -334,6 +358,9 @@
 
     private void configureAnimations(View... views) {
         for (View v : views) {
+            if (isDrawerView(v)) {
+                continue;
+            }
             v.animate()
                 .setInterpolator(mSlideInterpolator)
                 .setDuration(SLIDE_DURATION_MS);
@@ -342,14 +369,18 @@
 
     private void useHardwareLayer(boolean useHardware) {
         final int layerType = useHardware ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE;
-        mFoldersView.setLayerType(layerType, null);
+        if (!isDrawerView(mFoldersView)) {
+            mFoldersView.setLayerType(layerType, null);
+        }
         mListView.setLayerType(layerType, null);
         mListCopyView.setLayerType(layerType, null);
         mConversationView.setLayerType(layerType, null);
         if (useHardware) {
             // these buildLayer calls are safe because layout is the only way we get here
             // (i.e. these views must already be attached)
-            mFoldersView.buildLayer();
+            if (!isDrawerView(mFoldersView)) {
+                mFoldersView.buildLayer();
+            }
             mListView.buildLayer();
             mListCopyView.buildLayer();
             mConversationView.buildLayer();
@@ -434,8 +465,11 @@
     private int computeFolderListWidth(int parentWidth) {
         if (mIsSearchResult) {
             return 0;
+        } else if (isDrawerView(mFoldersView)) {
+            return 0;
+        } else {
+            return (int) (parentWidth * mFolderListWeight);
         }
-        return (int) (parentWidth * mFolderListWeight);
     }
 
     private void dispatchConversationListVisibilityChange(boolean visible) {
@@ -450,14 +484,19 @@
         }
     }
 
+    // does not apply to drawer children. will return zero for those.
     private int getPaneWidth(View pane) {
-        return pane.getLayoutParams().width;
+        return isDrawerView(pane) ? 0 : pane.getLayoutParams().width;
     }
 
     public View getConversationView() {
         return mConversationView;
     }
 
+    private boolean isDrawerView(View child) {
+        return child != null && child.getParent() == mDrawerLayout;
+    }
+
     /**
      * @return Whether or not the conversation list is visible on screen.
      */
@@ -475,6 +514,26 @@
             mConversationView.setVisibility(VISIBLE);
         }
 
+        // set up the drawer as appropriate for the configuration
+        final ViewParent foldersParent = mFoldersView.getParent();
+        if (mIsExpansiveLayout && foldersParent != this) {
+            if (foldersParent != mDrawerLayout) {
+                throw new IllegalStateException("invalid Folders fragment parent: " +
+                        foldersParent);
+            }
+            mDrawerLayout.removeView(mFoldersView);
+            addView(mFoldersView, 0);
+            mFoldersView.setBackgroundResource(R.drawable.drawer_shadow_tablet);
+        } else if (!mIsExpansiveLayout && foldersParent == this) {
+            removeView(mFoldersView);
+            mDrawerLayout.addView(mFoldersView);
+            final DrawerLayout.LayoutParams lp =
+                    (DrawerLayout.LayoutParams) mFoldersView.getLayoutParams();
+            lp.gravity = Gravity.START;
+            mFoldersView.setLayoutParams(lp);
+            mFoldersView.setBackgroundResource(R.color.list_background_color);
+        }
+
         // detach the pager immediately from its data source (to prevent processing updates)
         if (ViewMode.isConversationMode(mCurrentMode)) {
             mController.disablePagerUpdates();
@@ -499,6 +558,23 @@
         }
         lp.width = w;
         pane.setLayoutParams(lp);
+        if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
+            final String s;
+            if (pane == mFoldersView) {
+                s = "folders";
+            } else if (pane == mListView) {
+                s = "conv-list";
+            } else if (pane == mConversationView) {
+                s = "conv-view";
+            } else {
+                s = "???:" + pane;
+            }
+            LogUtils.d(LOG_TAG, "TPL: setPaneWidth, w=%spx pane=%s", w, s);
+        }
+    }
+
+    public boolean isDrawerEnabled() {
+        return !mIsExpansiveLayout;
     }
 
 }
diff --git a/src/com/android/mail/widget/BaseWidgetProvider.java b/src/com/android/mail/widget/BaseWidgetProvider.java
index b4b85c7..9dde2bb 100644
--- a/src/com/android/mail/widget/BaseWidgetProvider.java
+++ b/src/com/android/mail/widget/BaseWidgetProvider.java
@@ -60,6 +60,8 @@
 
 
     protected static final String ACTION_UPDATE_WIDGET = "com.android.mail.ACTION_UPDATE_WIDGET";
+    protected static final String
+            ACTION_VALIDATE_ALL_WIDGETS = "com.android.mail.ACTION_VALIDATE_ALL_WIDGETS";
     protected static final String EXTRA_WIDGET_ID = "widgetId";
 
     private static final String LOG_TAG = LogTag.getLogTag();
@@ -132,6 +134,8 @@
                 updateWidgetInternal(context, widgetId, account, folderType, folderUri,
                         folderConversationListUri, folderDisplayName);
             }
+        } else if (ACTION_VALIDATE_ALL_WIDGETS.equals(action)) {
+            validateAllWidgetInformation(context);
         } else if (Utils.ACTION_NOTIFY_DATASET_CHANGED.equals(action)) {
             // Receive notification for a certain account.
             final Bundle extras = intent.getExtras();
@@ -299,6 +303,12 @@
         context.sendBroadcast(updateWidgetIntent);
     }
 
+    public static void validateAllWidgets(Context context, String accountMimeType) {
+        final Intent migrateAllWidgetsIntent = new Intent(ACTION_VALIDATE_ALL_WIDGETS);
+        migrateAllWidgetsIntent.setType(accountMimeType);
+        context.sendBroadcast(migrateAllWidgetsIntent);
+    }
+
     protected void updateWidgetInternal(Context context, int appWidgetId, Account account,
             final int folderType, final Uri folderUri, final Uri folderConversationListUri,
             final String folderDisplayName) {
@@ -348,6 +358,23 @@
         return false;
     }
 
+    protected boolean isFolderValid(Context context, Uri folderUri) {
+        if (folderUri != null) {
+            final Cursor folderCursor =
+                    context.getContentResolver().query(folderUri,
+                            UIProvider.FOLDERS_PROJECTION, null, null, null);
+
+            try {
+                if (folderCursor.moveToFirst()) {
+                    return true;
+                }
+            } finally {
+                folderCursor.close();
+            }
+        }
+        return false;
+    }
+
     protected void configureValidAccountWidget(Context context, RemoteViews remoteViews,
             int appWidgetId, Account account, final int folderType, final Uri folderUri,
             final Uri folderConversationListUri, String folderDisplayName) {
@@ -371,6 +398,36 @@
         }
     }
 
+    private final void validateAllWidgetInformation(Context context) {
+        final int[] widgetIds = getCurrentWidgetIds(context);
+        for (int widgetId : widgetIds) {
+            final String accountFolder = MailPrefs.get(context).getWidgetConfiguration(widgetId);
+            String accountUri = null;
+            Uri folderUri = null;
+            if (!TextUtils.isEmpty(accountFolder)) {
+                final String[] parsedInfo = TextUtils.split(accountFolder,
+                        ACCOUNT_FOLDER_PREFERENCE_SEPARATOR);
+                if (parsedInfo.length == 2) {
+                    accountUri = parsedInfo[0];
+                    folderUri = Uri.parse(parsedInfo[1]);
+                } else {
+                    accountUri = accountFolder;
+                    folderUri =  Uri.EMPTY;
+                }
+            }
+
+            Account account = null;
+            if (!TextUtils.isEmpty(accountUri)) {
+                account = getAccountObject(context, accountUri);
+            }
+
+            // unconfigure the widget if it is not valid
+            if (!isAccountValid(context, account) || !isFolderValid(context, folderUri)) {
+                updateWidgetInternal(context, widgetId, null, FolderType.DEFAULT, null, null, null);
+            }
+        }
+    }
+
     /**
      * Abstract method allowing extending classes to perform widget migration
      */