Merge "Layout for Updates with multiple images."
diff --git a/res/layout/stream_item_one_column.xml b/res/layout/stream_item_container.xml
similarity index 95%
rename from res/layout/stream_item_one_column.xml
rename to res/layout/stream_item_container.xml
index ecab57c..1f96aad 100644
--- a/res/layout/stream_item_one_column.xml
+++ b/res/layout/stream_item_container.xml
@@ -19,16 +19,16 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <LinearLayout
+    <TableLayout
         android:id="@+id/stream_item_content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingTop="@dimen/detail_update_section_item_vertical_padding"
-        android:paddingBottom="@dimen/detail_update_section_item_vertical_padding"
+        android:paddingBottom="@dimen/detail_update_section_item_last_row_extra_vertical_padding"
         android:paddingLeft="@dimen/detail_update_section_item_horizontal_padding"
         android:paddingRight="@dimen/detail_update_section_item_horizontal_padding"
         android:background="@drawable/list_selector"
-        android:orientation="vertical" />
+        />
 
     <View
         android:id="@+id/horizontal_divider"
@@ -37,4 +37,5 @@
         android:layout_marginLeft="@dimen/detail_update_section_side_padding"
         android:layout_marginRight="@dimen/detail_update_section_side_padding"
         android:background="?android:attr/dividerHorizontal" />
+
 </LinearLayout>
diff --git a/res/layout/stream_item_pair.xml b/res/layout/stream_item_pair.xml
deleted file mode 100644
index 61b248c..0000000
--- a/res/layout/stream_item_pair.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <FrameLayout android:id="@+id/stream_pair_first"
-        android:layout_width="0dip"
-        android:layout_height="wrap_content"
-        android:layout_weight="1" />
-
-    <FrameLayout android:id="@+id/stream_pair_second"
-        android:paddingLeft="@dimen/detail_update_section_internal_padding"
-        android:layout_width="0dip"
-        android:layout_height="wrap_content"
-        android:layout_weight="1" />
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/stream_item_row_image_and_text.xml b/res/layout/stream_item_row_image_and_text.xml
new file mode 100644
index 0000000..b6f6599
--- /dev/null
+++ b/res/layout/stream_item_row_image_and_text.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<TableRow
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+    android:paddingBottom="@dimen/detail_update_section_between_items_vertical_padding">
+
+    <view
+        class="com.android.contacts.widget.ProportionalLayout"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="@dimen/detail_update_section_between_items_horizontal_padding"
+        android:layout_weight="1"
+        ex:ratio="1"
+        ex:direction="widthToHeight">
+        <ImageView
+            android:id="@+id/stream_item_first_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+    </view>
+
+    <view
+        class="com.android.contacts.widget.ProportionalLayout"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        ex:ratio="1"
+        ex:direction="widthToHeight">
+        <LinearLayout
+            android:id="@+id/stream_item_second_text"
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+            <TextView android:id="@+id/stream_item_html"
+                android:layout_width="match_parent"
+                android:layout_height="0dip"
+                android:layout_weight="1"
+                android:textSize="16sp"
+                android:textColor="?android:attr/textColorPrimary" />
+
+            <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <TextView android:id="@+id/stream_item_attribution"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:textColor="?android:attr/textColorSecondary" />
+
+                <TextView android:id="@+id/stream_item_comments"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/detail_update_section_attribution_comments_padding"
+                    android:textAppearance="?android:attr/textAppearanceSmall"
+                    android:textColor="?android:attr/textColorSecondary" />
+            </LinearLayout>
+
+        </LinearLayout>
+    </view>
+
+</TableRow>
diff --git a/res/layout/stream_item_text.xml b/res/layout/stream_item_row_text_only.xml
similarity index 76%
rename from res/layout/stream_item_text.xml
rename to res/layout/stream_item_row_text_only.xml
index 861d91f..d1d0efd 100644
--- a/res/layout/stream_item_text.xml
+++ b/res/layout/stream_item_row_text_only.xml
@@ -15,15 +15,16 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/detail_update_section_between_items_vertical_padding">
 
     <TextView android:id="@+id/stream_item_html"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textSize="16sp"
-        android:textColor="@color/social_update_text_color" />
+        android:textColor="?android:attr/textColorPrimary" />
 
     <LinearLayout
         android:orientation="horizontal"
@@ -33,14 +34,13 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="@color/social_update_attribution_color" />
+            android:textColor="?android:attr/textColorSecondary" />
 
         <TextView android:id="@+id/stream_item_comments"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="4dip"
+            android:layout_marginLeft="@dimen/detail_update_section_attribution_comments_padding"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="@color/social_update_comments_color" />
+            android:textColor="?android:attr/textColorSecondary" />
     </LinearLayout>
-
 </LinearLayout>
diff --git a/res/layout/stream_item_row_two_images.xml b/res/layout/stream_item_row_two_images.xml
new file mode 100644
index 0000000..6e34b25
--- /dev/null
+++ b/res/layout/stream_item_row_two_images.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<TableRow
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+    android:paddingBottom="@dimen/detail_update_section_between_items_vertical_padding">
+
+    <view
+        class="com.android.contacts.widget.ProportionalLayout"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="@dimen/detail_update_section_between_items_horizontal_padding"
+        android:layout_weight="1"
+        ex:ratio="1"
+        ex:direction="widthToHeight">
+        <ImageView
+            android:id="@+id/stream_item_first_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+    </view>
+
+    <view
+        class="com.android.contacts.widget.ProportionalLayout"
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        ex:ratio="1"
+        ex:direction="widthToHeight">
+        <ImageView
+            android:id="@+id/stream_item_second_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"/>
+    </view>
+
+</TableRow>
diff --git a/res/values-sw580dp/dimens.xml b/res/values-sw580dp/dimens.xml
index ed845be..7e3fb80 100644
--- a/res/values-sw580dp/dimens.xml
+++ b/res/values-sw580dp/dimens.xml
@@ -33,6 +33,7 @@
     <dimen name="shortcut_icon_size">64dip</dimen>
     <dimen name="list_section_height">37dip</dimen>
     <dimen name="detail_update_section_item_vertical_padding">32dip</dimen>
+    <dimen name="detail_update_section_item_last_row_extra_vertical_padding">16dip</dimen>
     <dimen name="search_view_width">400dip</dimen>
     <!-- Center vertically -->
     <dimen name="quick_contact_top_position">-1px</dimen>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a9d745f..0005484 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -31,12 +31,6 @@
 
     <color name="background_social_updates">#ffeeeeee</color>
 
-    <color name="social_update_text_color">#ff333333</color>
-
-    <color name="social_update_attribution_color">#ff777777</color>
-
-    <color name="social_update_comments_color">#ff777777</color>
-
     <!-- Color used for the letter in the A-Z section header -->
     <color name="section_header_text_color">#ff999999</color>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1b737bc..459d0f8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -108,12 +108,28 @@
     <!-- Vertical padding above and below individual stream items -->
     <dimen name="detail_update_section_item_vertical_padding">16dip</dimen>
 
+    <!-- Vertical padding between rows of images in a single stream item -->
+    <dimen name="detail_update_section_between_items_vertical_padding">16dip</dimen>
+
+    <!-- The extra padding to be added at the end of last row in a stream items, i.e., the
+         difference between detail_update_section_item_vertical_padding and
+         detail_update_section_between_items_vertical_padding
+      -->
+    <dimen name="detail_update_section_item_last_row_extra_vertical_padding">0dip</dimen>
+
     <!-- Horizontal padding for individual stream items -->
     <dimen name="detail_update_section_item_horizontal_padding">24dip</dimen>
 
+    <!-- Horizontal padding between columns images and/or text in a single stream item -->
+    <dimen name="detail_update_section_between_items_horizontal_padding">16dip</dimen>
+
     <!-- Horizontal padding between content sections within a stream item -->
     <dimen name="detail_update_section_internal_padding">16dip</dimen>
 
+    <!-- Horizontal padding between attribution and comments -->
+    <dimen name="detail_update_section_attribution_comments_padding">4dip</dimen>
+
+
     <!-- Margin around the contact's photo on the contact card -->
     <dimen name="detail_contact_photo_margin">16dip</dimen>
 
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 3bff950..94150b3 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -60,7 +60,6 @@
  * {@link ContactLoader.Result} data object to appropriate {@link View}s.
  */
 public class ContactDetailDisplayUtils {
-
     private static final int PHOTO_FADE_IN_ANIMATION_DURATION_MILLIS = 100;
 
     private ContactDetailDisplayUtils() {
@@ -252,83 +251,68 @@
     /** Creates the view that represents a stream item. */
     public static View createStreamItemView(LayoutInflater inflater, Context context,
             StreamItemEntry streamItem, LinearLayout parent) {
-        View oneColumnView = inflater.inflate(R.layout.stream_item_one_column,
-                parent, false);
-        ViewGroup contentBox = (ViewGroup) oneColumnView.findViewById(R.id.stream_item_content);
-        int internalPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.detail_update_section_internal_padding);
+        View container = inflater.inflate(R.layout.stream_item_container, parent, false);
+        ViewGroup contentTable = (ViewGroup) container.findViewById(R.id.stream_item_content);
 
-        // TODO: This is not the correct layout for a stream item with photos.  Photos should be
-        // displayed first, then the update text either to the right of the final image (if there
-        // are an odd number of images) or below the last row of images (if there are an even
-        // number of images).  Since this is designed as a two-column grid, we should also consider
-        // using a TableLayout instead of the series of nested LinearLayouts that we have now.
-        // See the Updates section of the Contacts Architecture document for details.
-
-        // If there are no photos, just display the text in a single column.
+        ContactPhotoManager contactPhotoManager = ContactPhotoManager.getInstance(context);
         List<StreamItemPhotoEntry> photos = streamItem.getPhotos();
-        if (photos.isEmpty()) {
-            addStreamItemText(inflater, context, streamItem, contentBox);
-        } else {
-            // If the first photo is square or portrait mode, show the text alongside it.
-            boolean isFirstPhotoAlongsideText = false;
-            StreamItemPhotoEntry firstPhoto = photos.get(0);
-            isFirstPhotoAlongsideText = firstPhoto.getHeight() >= firstPhoto.getWidth();
-            if (isFirstPhotoAlongsideText) {
-                View twoColumnView = inflater.inflate(R.layout.stream_item_pair, contentBox, false);
-                addStreamItemPhoto(inflater, context, firstPhoto,
-                        (ViewGroup) twoColumnView.findViewById(R.id.stream_pair_first));
-                addStreamItemText(inflater, context, streamItem,
-                        (ViewGroup) twoColumnView.findViewById(R.id.stream_pair_second));
-                contentBox.addView(twoColumnView);
-            } else {
-                // Just add the stream item text at the top of the entry.
-                addStreamItemText(inflater, context, streamItem, contentBox);
-            }
-            for (int i = isFirstPhotoAlongsideText ? 1 : 0; i < photos.size(); i++) {
-                StreamItemPhotoEntry photo = photos.get(i);
+        final int photoCount = photos.size();
 
-                // If the photo is landscape, show it at full-width.
-                if (photo.getWidth() > photo.getHeight()) {
-                    View photoView = addStreamItemPhoto(inflater, context, photo, contentBox);
-                    photoView.setPadding(0, internalPadding, 0, 0);
-                } else {
-                    // If this photo and the next are both square or portrait, show them as a pair.
-                    StreamItemPhotoEntry nextPhoto = i + 1 < photos.size()
-                            ? photos.get(i + 1) : null;
-                    if (nextPhoto != null && nextPhoto.getHeight() >= nextPhoto.getWidth()) {
-                        View twoColumnView = inflater.inflate(R.layout.stream_item_pair,
-                                contentBox, false);
-                        addStreamItemPhoto(inflater, context, photo,
-                                (ViewGroup) twoColumnView.findViewById(R.id.stream_pair_first));
-                        addStreamItemPhoto(inflater, context, nextPhoto,
-                                (ViewGroup) twoColumnView.findViewById(R.id.stream_pair_second));
-                        twoColumnView.setPadding(0, internalPadding, 0, 0);
-                        contentBox.addView(twoColumnView);
-                        i++;
-                    } else {
-                        View photoView = addStreamItemPhoto(inflater, context, photo, contentBox);
-                        photoView.setPadding(0, internalPadding, 0, 0);
-                    }
-                }
+        // Process the photos, two at a time.
+        for (int index = 0; index < photoCount; index += 2) {
+            final StreamItemPhotoEntry firstPhoto = photos.get(index);
+            if (index + 1 < photoCount) {
+                // Put in two photos, side by side.
+                final StreamItemPhotoEntry secondPhoto = photos.get(index + 1);
+
+                View photoContainer = inflater.inflate(R.layout.stream_item_row_two_images,
+                        contentTable, false);
+                loadPhoto(contactPhotoManager, firstPhoto, photoContainer,
+                        R.id.stream_item_first_image);
+                loadPhoto(contactPhotoManager, secondPhoto, photoContainer,
+                        R.id.stream_item_second_image);
+                contentTable.addView(photoContainer);
+            } else {
+                // Put in a single photo with text on the side.
+                View photoContainer = inflater.inflate(
+                        R.layout.stream_item_row_image_and_text, contentTable, false);
+                loadPhoto(contactPhotoManager, firstPhoto, photoContainer,
+                        R.id.stream_item_first_image);
+                addStreamItemText(context, streamItem,
+                        photoContainer.findViewById(R.id.stream_item_second_text));
+                contentTable.addView(photoContainer);
             }
         }
 
+        if (photoCount % 2 == 0) {
+            // Even number of photos, add the text below them. Otherwise, it should have been
+            // already added next to the last photo.
+            View textContainer = inflater.inflate(R.layout.stream_item_row_text_only, contentTable,
+                    false);
+            addStreamItemText(context, streamItem, textContainer);
+            contentTable.addView(textContainer);
+        }
+
         if (parent != null) {
-            parent.addView(oneColumnView);
+            parent.addView(container);
         }
 
-        return oneColumnView;
+        return container;
+    }
+
+    /** Loads a photo into an image view. The image view is identifiedc by the given id. */
+    private static void loadPhoto(ContactPhotoManager contactPhotoManager,
+            final StreamItemPhotoEntry firstPhoto, View photoContainer, int imageViewId) {
+        ImageView firstImageView = (ImageView) photoContainer.findViewById(imageViewId);
+        contactPhotoManager.loadPhoto(firstImageView, Uri.parse(firstPhoto.getPhotoUri()));
     }
 
     @VisibleForTesting
-    static View addStreamItemText(LayoutInflater inflater, Context context,
-            StreamItemEntry streamItem, ViewGroup parent) {
-        View textUpdate = inflater.inflate(R.layout.stream_item_text, parent, false);
-        TextView htmlView = (TextView) textUpdate.findViewById(R.id.stream_item_html);
-        TextView attributionView = (TextView) textUpdate.findViewById(
+    static View addStreamItemText(Context context, StreamItemEntry streamItem, View rootView) {
+        TextView htmlView = (TextView) rootView.findViewById(R.id.stream_item_html);
+        TextView attributionView = (TextView) rootView.findViewById(
                 R.id.stream_item_attribution);
-        TextView commentsView = (TextView) textUpdate.findViewById(R.id.stream_item_comments);
+        TextView commentsView = (TextView) rootView.findViewById(R.id.stream_item_comments);
         htmlView.setText(Html.fromHtml(streamItem.getText()));
         attributionView.setText(ContactBadgeUtil.getSocialDate(streamItem, context));
         if (streamItem.getComments() != null) {
@@ -337,19 +321,7 @@
         } else {
             commentsView.setVisibility(View.GONE);
         }
-        if (parent != null) {
-            parent.addView(textUpdate);
-        }
-        return textUpdate;
-    }
-
-    private static View addStreamItemPhoto(LayoutInflater inflater, Context context,
-            StreamItemPhotoEntry streamItemPhoto, ViewGroup parent) {
-        ImageView image = new ImageView(context);
-        ContactPhotoManager.getInstance(context).loadPhoto(
-                image, Uri.parse(streamItemPhoto.getPhotoUri()));
-        parent.addView(image);
-        return image;
+        return rootView;
     }
 
     /**
diff --git a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
index aebb8c2..487eec9 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailDisplayUtilsTest.java
@@ -27,7 +27,6 @@
 import android.text.Spanned;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.TextView;
 
 /**
@@ -105,11 +104,11 @@
 
     /**
      * Calls {@link ContactDetailDisplayUtils#addStreamItemText(LayoutInflater, Context,
-     * StreamItemEntry, ViewGroup)} with the default parameters and the given stream item.
+     * StreamItemEntry, View)} with the default parameters and the given stream item.
      */
     private View addStreamItemText(StreamItemEntry streamItem) {
-        return ContactDetailDisplayUtils.addStreamItemText(
-                mLayoutInflater, getContext(), streamItem, null);
+        return ContactDetailDisplayUtils.addStreamItemText(getContext(), streamItem,
+                mLayoutInflater.inflate(R.layout.stream_item_row_text_only, null));
     }
 
     private StreamItemEntryBuilder getTestBuilder() {