Settings, replace files, sorting by size, tweaks.

Add settings to show file sizes and advanced storage devices, both
disabled by default. Add sorting by size when enabled in settings.

Always show all documents, but only allow selection when they match
MIME filter. When creating, select entire filename on focus. When
creating, treat selected documents as replacement targets using that
exact Uri unless display name is changed.

Show available bytes for device roots. Show empty text label in
empty directories. Split grid backend and details into two separate
lines. Fix path label ordering when rendering recent directories.

Change-Id: I44c62e8adb8ca7d4355510a13d1ba975196a2d29
diff --git a/src/com/android/documentsui/DirectoryFragment.java b/src/com/android/documentsui/DirectoryFragment.java
index d986a51..5a6060a 100644
--- a/src/com/android/documentsui/DirectoryFragment.java
+++ b/src/com/android/documentsui/DirectoryFragment.java
@@ -27,7 +27,6 @@
 import android.provider.DocumentsContract;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
-import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.ActionMode;
 import android.view.LayoutInflater;
@@ -62,11 +61,14 @@
  */
 public class DirectoryFragment extends Fragment {
 
+    private View mEmptyView;
     private ListView mListView;
     private GridView mGridView;
 
     private AbsListView mCurrentView;
 
+    private Predicate<Document> mFilter;
+
     public static final int TYPE_NORMAL = 1;
     public static final int TYPE_SEARCH = 2;
     public static final int TYPE_RECENT_OPEN = 3;
@@ -121,6 +123,8 @@
 
         final View view = inflater.inflate(R.layout.fragment_directory, container, false);
 
+        mEmptyView = view.findViewById(android.R.id.empty);
+
         mListView = (ListView) view.findViewById(R.id.list);
         mListView.setOnItemClickListener(mItemListener);
         mListView.setMultiChoiceModeListener(mMultiListener);
@@ -138,6 +142,7 @@
             @Override
             public Loader<List<Document>> onCreateLoader(int id, Bundle args) {
                 final DisplayState state = getDisplayState(DirectoryFragment.this);
+                mFilter = new MimePredicate(state.acceptMimes);
 
                 final Uri contentsUri;
                 if (mType == TYPE_NORMAL) {
@@ -148,18 +153,18 @@
                     contentsUri = uri;
                 }
 
-                final Predicate<Document> filter = new MimePredicate(state.acceptMimes);
-
                 final Comparator<Document> sortOrder;
                 if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
                     sortOrder = new Document.DateComparator();
                 } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) {
                     sortOrder = new Document.NameComparator();
+                } else if (state.sortOrder == DisplayState.SORT_ORDER_SIZE) {
+                    sortOrder = new Document.SizeComparator();
                 } else {
                     throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
                 }
 
-                return new DirectoryLoader(context, contentsUri, mType, filter, sortOrder);
+                return new DirectoryLoader(context, contentsUri, mType, null, sortOrder);
             }
 
             @Override
@@ -181,6 +186,10 @@
     @Override
     public void onStart() {
         super.onStart();
+
+        final Context context = getActivity();
+        getDisplayState(this).showSize = SettingsActivity.getDisplayFileSize(context);
+
         getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
     }
 
@@ -193,7 +202,7 @@
     public void updateDisplayState() {
         final DisplayState state = getDisplayState(this);
 
-        // TODO: avoid kicking loader when sort didn't change
+        // TODO: avoid kicking loader when nothing changed
         getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
         mListView.smoothScrollToPosition(0);
         mGridView.smoothScrollToPosition(0);
@@ -302,6 +311,13 @@
 
         public void swapDocuments(List<Document> documents) {
             mDocuments = documents;
+
+            if (documents != null && documents.isEmpty()) {
+                mEmptyView.setVisibility(View.VISIBLE);
+            } else {
+                mEmptyView.setVisibility(View.GONE);
+            }
+
             notifyDataSetChanged();
         }
 
@@ -325,6 +341,7 @@
 
             final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
             final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final View summaryGrid = convertView.findViewById(R.id.summary_grid);
             final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
             final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
             final TextView date = (TextView) convertView.findViewById(R.id.date);
@@ -356,6 +373,11 @@
                 summary.setVisibility(View.VISIBLE);
             }
 
+            if (summaryGrid != null) {
+                summaryGrid.setVisibility(
+                        (summary.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE);
+            }
+
             // TODO: omit year from format
             date.setText(DateUtils.formatSameDayTime(
                     doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT,
@@ -389,5 +411,16 @@
         public long getItemId(int position) {
             return getItem(position).uri.hashCode();
         }
+
+        @Override
+        public boolean areAllItemsEnabled() {
+            return false;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            final Document doc = getItem(position);
+            return mFilter.apply(doc);
+        }
     }
 }