WidgetTray improvement

UI
- Fixing the issue of widget row not rendering
- Moved the resetting of previous bitmap to the start of onBind
instead of the onDetachedWindow.

Performance
- WidgetModel do not have to keep packageName list around.

Will com in immediate follow up CLs
- use lowRes widgets bitmap before fully loading the fullRes one.
- application icons are fully loaded in background thread.

b/19897708

Change-Id: I5b3b43a5c543a5135c395f90df32e66d57dc86e0
diff --git a/res/layout/widget_cell.xml b/res/layout/widget_cell.xml
index 9e91f67..a5b25aa 100644
--- a/res/layout/widget_cell.xml
+++ b/res/layout/widget_cell.xml
@@ -57,7 +57,6 @@
             android:id="@+id/widget_dims"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="center"
             android:layout_marginStart="5dp"
             android:layout_marginLeft="5dp"
             android:layout_weight="0"
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3d2a346..42e145b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -132,7 +132,7 @@
         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                    View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener,
                    LauncherStateTransitionAnimation.Callbacks {
-    static final String TAG = "Launcher - MERONG";
+    static final String TAG = "Launcher";
     static final boolean LOGD = true;
 
     static final boolean PROFILE_STARTUP = false;
diff --git a/src/com/android/launcher3/widget/PackageItemInfo.java b/src/com/android/launcher3/widget/PackageItemInfo.java
index d7edf22..1a1de55 100644
--- a/src/com/android/launcher3/widget/PackageItemInfo.java
+++ b/src/com/android/launcher3/widget/PackageItemInfo.java
@@ -39,11 +39,12 @@
      */
     public boolean usingLowResIcon;
 
-    public ComponentName componentName;
+    public String packageName;
 
     int flags = 0;
 
-    PackageItemInfo() {
+    PackageItemInfo(String packageName) {
+        this.packageName = packageName;
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 93ee94a..d10c304 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -47,7 +47,7 @@
  */
 public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
 
-    private static final String TAG = "PagedViewWidget";
+    private static final String TAG = "WidgetCell";
     private static final boolean DEBUG = false;
 
     // Temporary preset width and height of the image to keep them aligned.
@@ -120,7 +120,16 @@
             Log.d(TAG, String.format("[tag=%s] onDetachedFromWindow", getTagToString()));
         }
         super.onDetachedFromWindow();
-        deletePreview(true);
+        deletePreview(false);
+    }
+
+    public void reset() {
+        ImageView image = (ImageView) findViewById(R.id.widget_preview);
+        final TextView name = (TextView) findViewById(R.id.widget_name);
+        final TextView dims = (TextView) findViewById(R.id.widget_dims);
+        image.setImageDrawable(null);
+        name.setText(null);
+        dims.setText(null);
     }
 
     public void deletePreview(boolean recycleImage) {
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index 8d1f20c..afeb2d3 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -88,14 +88,13 @@
 
     @Override
     public void onBindViewHolder(WidgetsRowViewHolder holder, int pos) {
-        String packageName = mWidgetsModel.getPackageName(pos);
-        List<Object> infoList = mWidgetsModel.getSortedWidgets(packageName);
+        List<Object> infoList = mWidgetsModel.getSortedWidgets(pos);
 
         ViewGroup row = ((ViewGroup) holder.getContent().findViewById(R.id.widgets_cell_list));
         if (DEBUG) {
             Log.d(TAG, String.format(
-                    "onBindViewHolder [pos=%d, packageName=%s, widget#=%d, row.getChildCount=%d]",
-                    pos, packageName, infoList.size(), row.getChildCount()));
+                    "onBindViewHolder [pos=%d, widget#=%d, row.getChildCount=%d]",
+                    pos, infoList.size(), row.getChildCount()));
         }
 
         // Add more views.
@@ -120,11 +119,11 @@
         }
 
         // Bind the views in the application info section.
-        PackageItemInfo infoOut = mWidgetsModel.getPackageItemInfo(packageName);
+        PackageItemInfo infoOut = mWidgetsModel.getPackageItemInfo(pos);
         if (infoOut.usingLowResIcon) {
-            mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(),
-                false /* useLowResIcon */, infoOut);
-            mWidgetsModel.setPackageItemInfo(packageName, infoOut);
+            // TODO(hyunyoungs): call this in none UI thread in the same way as BubbleTextView.
+            mIconCache.getTitleAndIconForApp(infoOut.packageName,
+                    UserHandleCompat.myUserHandle(), false /* useLowResIcon */, infoOut);
         }
         ((TextView) holder.getContent().findViewById(R.id.section)).setText(infoOut.title);
         ImageView iv = (ImageView) holder.getContent().findViewById(R.id.section_image);
@@ -133,7 +132,8 @@
         // Bind the view in the widget horizontal tray region.
         for (int i=0; i < infoList.size(); i++) {
             WidgetCell widget = (WidgetCell) row.getChildAt(i);
-            if (getWidgetPreviewLoader() == null || widget == null) {
+            widget.reset();
+            if (getWidgetPreviewLoader() == null) {
                 return;
             }
             if (infoList.get(i) instanceof LauncherAppWidgetProviderInfo) {
@@ -150,7 +150,6 @@
             widget.setVisibility(View.VISIBLE);
             widget.ensurePreview();
         }
-        // TODO(hyunyoungs): Draw the scrollable indicator.
     }
 
     @Override
@@ -175,15 +174,4 @@
         }
         return mWidgetPreviewLoader;
     }
-
-    /**
-     * TODO(hyunyoungs): this is temporary. Figure out the width of each widget cell
-     * and then check if the total sum is longer than the parent width.
-     */
-    private void addScrollableIndicator(int contentSize, ViewGroup parent) {
-        if (contentSize > 2) {
-            ViewGroup indicator = (ViewGroup) parent.findViewById(R.id.scrollable_indicator);
-            indicator.setVisibility(View.VISIBLE);
-        }
-    }
 }
diff --git a/src/com/android/launcher3/widget/WidgetsModel.java b/src/com/android/launcher3/widget/WidgetsModel.java
index 463c79e..1447bef 100644
--- a/src/com/android/launcher3/widget/WidgetsModel.java
+++ b/src/com/android/launcher3/widget/WidgetsModel.java
@@ -31,12 +31,10 @@
     private static final boolean DEBUG = false;
 
     /* List of packages that is tracked by this model. */
-    private List<String> mPackageNames = new ArrayList<>();
-
-    private Map<String, PackageItemInfo> mPackageItemInfoList = new HashMap<>();
+    private List<PackageItemInfo> mPackageItemInfos = new ArrayList<>();
 
     /* Map of widgets and shortcuts that are tracked per package. */
-    private Map<String, ArrayList<Object>> mWidgetsList = new HashMap<>();
+    private Map<PackageItemInfo, ArrayList<Object>> mWidgetsList = new HashMap<>();
 
     /* Notifies the adapter when data changes. */
     private RecyclerView.Adapter mAdapter;
@@ -53,20 +51,16 @@
 
     // Access methods that may be deleted if the private fields are made package-private.
     public int getPackageSize() {
-        return mPackageNames.size();
+        return mPackageItemInfos.size();
     }
 
     // Access methods that may be deleted if the private fields are made package-private.
-    public String getPackageName(int pos) {
-        return mPackageNames.get(pos);
+    public PackageItemInfo getPackageItemInfo(int pos) {
+        return mPackageItemInfos.get(pos);
     }
 
-    public PackageItemInfo getPackageItemInfo(String packageName) {
-        return mPackageItemInfoList.get(packageName);
-    }
-
-    public List<Object> getSortedWidgets(String packageName) {
-        return mWidgetsList.get(packageName);
+    public List<Object> getSortedWidgets(int pos) {
+        return mWidgetsList.get(mPackageItemInfos.get(pos));
     }
 
     public void addWidgetsAndShortcuts(ArrayList<Object> widgetsShortcuts, PackageManager pm) {
@@ -74,8 +68,10 @@
             Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + widgetsShortcuts.size());
         }
 
+        // Temporary list for {@link PackageItemInfos} to avoid having to go through
+        // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList}
+        HashMap<String, PackageItemInfo> tmpPackageItemInfos = new HashMap<>();
         // clear the lists.
-        mPackageNames.clear();
         mWidgetsList.clear();
 
         // add and update.
@@ -90,51 +86,41 @@
             } else {
                 Log.e(TAG, String.format("addWidgetsAndShortcuts, nothing added for class=%s",
                         o.getClass().toString()));
-                
             }
 
-            ArrayList<Object> widgetsShortcutsList = mWidgetsList.get(packageName);
+            PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
+            ArrayList<Object> widgetsShortcutsList = mWidgetsList.get(pInfo);
             if (widgetsShortcutsList != null) {
                 widgetsShortcutsList.add(o);
             } else {
                 widgetsShortcutsList = new ArrayList<Object>();
                 widgetsShortcutsList.add(o);
-                mWidgetsList.put(packageName, widgetsShortcutsList);
-                mPackageNames.add(packageName);
-            }
-        }
-        for (String packageName: mPackageNames) {
-            PackageItemInfo pInfo = mPackageItemInfoList.get(packageName);
-            if (pInfo == null) {
-                pInfo = new PackageItemInfo();
+
+                pInfo = new PackageItemInfo(packageName);
                 mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(),
                         true /* useLowResIcon */, pInfo);
-                mPackageItemInfoList.put(packageName, pInfo);
+                mWidgetsList.put(pInfo, widgetsShortcutsList);
+                tmpPackageItemInfos.put(packageName,  pInfo);
+                mPackageItemInfos.add(pInfo);
             }
         }
 
         // sort.
-        sortPackageList();
-        for (String packageName: mPackageNames) {
-            Collections.sort(mWidgetsList.get(packageName), mWidgetAndShortcutNameComparator);
+        sortPackageItemInfos();
+        for (PackageItemInfo p: mPackageItemInfos) {
+            Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator);
         }
 
         // notify.
         mAdapter.notifyDataSetChanged();
     }
 
-    private void sortPackageList() {
-        Collections.sort(mPackageNames, new Comparator<String>() {
+    private void sortPackageItemInfos() {
+        Collections.sort(mPackageItemInfos, new Comparator<PackageItemInfo>() {
             @Override
-            public int compare(String lhs, String rhs) {
-                String lhsTitle = mPackageItemInfoList.get(lhs).title.toString();
-                String rhsTitle = mPackageItemInfoList.get(rhs).title.toString();
-                return lhsTitle.compareTo(rhsTitle);
+            public int compare(PackageItemInfo lhs, PackageItemInfo rhs) {
+                return lhs.title.toString().compareTo(rhs.title.toString());
             }
         });
     }
-
-    public void setPackageItemInfo(String packageName, PackageItemInfo infoOut) {
-        mPackageItemInfoList.put(packageName, infoOut);
-    }
-}
+}
\ No newline at end of file