diff options
16 files changed, 627 insertions, 248 deletions
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index b88099ef64f0..1d97161fdccb 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -3,7 +3,10 @@ <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" /> - <application android:label="@string/app_label"> + <application + android:label="@string/app_label" + android:supportsRtl="true"> + <activity android:name=".DocumentsActivity" android:finishOnCloseSystemDialogs="true" diff --git a/packages/DocumentsUI/res/layout/fragment_roots.xml b/packages/DocumentsUI/res/layout/fragment_roots.xml index d77289216097..09782d9349b7 100644 --- a/packages/DocumentsUI/res/layout/fragment_roots.xml +++ b/packages/DocumentsUI/res/layout/fragment_roots.xml @@ -17,4 +17,5 @@ <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + android:divider="@null" /> diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml index caa9db664179..ad8f51cb1a07 100644 --- a/packages/DocumentsUI/res/layout/item_doc_grid.xml +++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml @@ -16,7 +16,7 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="140dip" + android:layout_height="160dip" android:paddingBottom="?android:attr/listPreferredItemPaddingEnd" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> @@ -27,16 +27,16 @@ android:foreground="@drawable/item_background" android:duplicateParentState="true"> - <GridLayout + <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" - android:columnCount="1"> + android:orientation="vertical"> <ImageView android:id="@android:id/icon" android:layout_width="match_parent" android:layout_height="0dip" - android:layout_gravity="fill_vertical" + android:layout_weight="1" android:background="#bbb" android:scaleType="centerInside" android:contentDescription="@null" /> @@ -44,16 +44,67 @@ <TextView android:id="@android:id/title" android:layout_width="match_parent" - android:layout_marginStart="8dip" - android:layout_marginEnd="8dip" - android:layout_marginTop="8dip" - android:layout_marginBottom="8dip" + android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" + android:paddingTop="6dp" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:textAppearance="?android:attr/textAppearanceSmall" android:textAlignment="viewStart" /> - </GridLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingBottom="6dp" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + <ImageView + android:id="@android:id/icon1" + android:layout_width="24dip" + android:layout_height="24dip" + android:layout_marginEnd="6dip" + android:scaleType="centerInside" + android:contentDescription="@null" /> + + <TextView + android:id="@android:id/summary" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewStart" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <TextView + android:id="@+id/size" + android:layout_width="70dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewEnd" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <TextView + android:id="@+id/date" + android:layout_width="70dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewEnd" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + </LinearLayout> + + </LinearLayout> </FrameLayout> diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml index 39e55beef5db..bb2717372370 100644 --- a/packages/DocumentsUI/res/layout/item_doc_list.xml +++ b/packages/DocumentsUI/res/layout/item_doc_list.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/item_background" @@ -23,40 +23,82 @@ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingTop="8dip" android:paddingBottom="8dip" - android:columnCount="3"> + android:orientation="horizontal"> <ImageView android:id="@android:id/icon" android:layout_width="@android:dimen/app_icon_size" android:layout_height="@android:dimen/app_icon_size" - android:layout_rowSpan="2" android:layout_marginEnd="8dip" + android:layout_gravity="center_vertical" android:scaleType="centerInside" android:contentDescription="@null" /> - <TextView - android:id="@android:id/title" + <LinearLayout android:layout_width="0dip" - android:layout_gravity="fill_horizontal" - android:layout_marginTop="2dip" - android:layout_columnSpan="2" - android:singleLine="true" - android:ellipsize="marquee" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textAlignment="viewStart" /> + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:orientation="vertical"> - <ImageView - android:id="@android:id/icon1" - android:layout_width="24dip" - android:layout_height="24dip" - android:layout_marginEnd="8dip" - android:visibility="gone" - android:scaleType="centerInside" - android:contentDescription="@null" /> + <TextView + android:id="@android:id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textAlignment="viewStart" /> + + <LinearLayout + android:id="@+id/line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <ImageView + android:id="@android:id/icon1" + android:layout_width="24dip" + android:layout_height="24dip" + android:layout_marginEnd="6dip" + android:scaleType="centerInside" + android:contentDescription="@null" /> + + <TextView + android:id="@android:id/summary" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewStart" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <TextView + android:id="@+id/size" + android:layout_width="70dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewEnd" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <TextView + android:id="@+id/date" + android:layout_width="70dp" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:singleLine="true" + android:ellipsize="marquee" + android:textAlignment="viewEnd" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + </LinearLayout> - <TextView - android:id="@android:id/summary" - android:layout_marginTop="2dip" - android:textAppearance="?android:attr/textAppearanceSmall" /> + </LinearLayout> -</GridLayout> +</LinearLayout> diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml index a0d03b251699..d57f88ab247b 100644 --- a/packages/DocumentsUI/res/menu/activity.xml +++ b/packages/DocumentsUI/res/menu/activity.xml @@ -27,4 +27,14 @@ android:showAsAction="always|collapseActionView" android:actionViewClass="android.widget.SearchView" android:imeOptions="actionSearch" /> + <item + android:id="@+id/menu_grid" + android:title="@string/menu_grid" + android:icon="@drawable/ic_menu_grid" + android:showAsAction="ifRoom" /> + <item + android:id="@+id/menu_list" + android:title="@string/menu_list" + android:icon="@drawable/ic_menu_list" + android:showAsAction="ifRoom" /> </menu> diff --git a/packages/DocumentsUI/res/menu/directory.xml b/packages/DocumentsUI/res/menu/directory.xml deleted file mode 100644 index 12d0324fb26e..000000000000 --- a/packages/DocumentsUI/res/menu/directory.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2013 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. ---> - -<menu xmlns:android="http://schemas.android.com/apk/res/android"> - <item - android:id="@+id/menu_grid" - android:title="@string/menu_grid" - android:icon="@drawable/ic_menu_grid" - android:showAsAction="ifRoom" /> - <item - android:id="@+id/menu_list" - android:title="@string/menu_list" - android:icon="@drawable/ic_menu_list" - android:showAsAction="ifRoom" /> -</menu> diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index 1443f2679efb..d986a512e9da 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -26,11 +26,12 @@ import android.net.Uri; import android.os.Bundle; 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; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -46,20 +47,21 @@ import android.widget.TextView; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.model.Document; +import com.android.documentsui.model.Root; import com.android.internal.util.Predicate; import com.google.android.collect.Lists; +import java.text.DateFormat; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; /** * Display the documents inside a single directory. */ public class DirectoryFragment extends Fragment { - // TODO: show storage backend in item views when requested - private ListView mListView; private GridView mGridView; @@ -68,19 +70,35 @@ public class DirectoryFragment extends Fragment { public static final int TYPE_NORMAL = 1; public static final int TYPE_SEARCH = 2; public static final int TYPE_RECENT_OPEN = 3; - public static final int TYPE_RECENT_CREATE = 4; private int mType = TYPE_NORMAL; private DocumentsAdapter mAdapter; private LoaderCallbacks<List<Document>> mCallbacks; + private static final String EXTRA_TYPE = "type"; private static final String EXTRA_URI = "uri"; - private static final int LOADER_DOCUMENTS = 2; + private static AtomicInteger sLoaderId = new AtomicInteger(4000); + + private final int mLoaderId = sLoaderId.incrementAndGet(); + + public static void showNormal(FragmentManager fm, Uri uri) { + show(fm, TYPE_NORMAL, uri); + } + + public static void showSearch(FragmentManager fm, Uri uri, String query) { + final Uri searchUri = DocumentsContract.buildSearchUri(uri, query); + show(fm, TYPE_SEARCH, searchUri); + } + + public static void showRecentsOpen(FragmentManager fm) { + show(fm, TYPE_RECENT_OPEN, null); + } - public static void show(FragmentManager fm, Uri uri) { + private static void show(FragmentManager fm, int type, Uri uri) { final Bundle args = new Bundle(); + args.putInt(EXTRA_TYPE, type); args.putParcelable(EXTRA_URI, uri); final DirectoryFragment fragment = new DirectoryFragment(); @@ -97,12 +115,6 @@ public class DirectoryFragment extends Fragment { } @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Context context = inflater.getContext(); @@ -118,19 +130,9 @@ public class DirectoryFragment extends Fragment { mGridView.setMultiChoiceModeListener(mMultiListener); mAdapter = new DocumentsAdapter(); - updateMode(); final Uri uri = getArguments().getParcelable(EXTRA_URI); - - if (uri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { - mType = TYPE_SEARCH; - } else if (RecentsProvider.buildRecentOpen().equals(uri)) { - mType = TYPE_RECENT_OPEN; - } else if (RecentsProvider.buildRecentCreate().equals(uri)) { - mType = TYPE_RECENT_CREATE; - } else { - mType = TYPE_NORMAL; - } + mType = getArguments().getInt(EXTRA_TYPE); mCallbacks = new LoaderCallbacks<List<Document>>() { @Override @@ -140,6 +142,8 @@ public class DirectoryFragment extends Fragment { final Uri contentsUri; if (mType == TYPE_NORMAL) { contentsUri = DocumentsContract.buildContentsUri(uri); + } else if (mType == TYPE_RECENT_OPEN) { + contentsUri = RecentsProvider.buildRecentOpen(); } else { contentsUri = uri; } @@ -147,8 +151,7 @@ public class DirectoryFragment extends Fragment { final Predicate<Document> filter = new MimePredicate(state.acceptMimes); final Comparator<Document> sortOrder; - if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN - || mType == TYPE_RECENT_CREATE) { + 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(); @@ -170,56 +173,30 @@ public class DirectoryFragment extends Fragment { } }; + updateDisplayState(); + return view; } @Override public void onStart() { super.onStart(); - getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); + getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks); } @Override public void onStop() { super.onStop(); - getLoaderManager().destroyLoader(LOADER_DOCUMENTS); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.directory, menu); + getLoaderManager().destroyLoader(mLoaderId); } - @Override - public void onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); + public void updateDisplayState() { final DisplayState state = getDisplayState(this); - menu.findItem(R.id.menu_grid).setVisible(state.mode != DisplayState.MODE_GRID); - menu.findItem(R.id.menu_list).setVisible(state.mode != DisplayState.MODE_LIST); - } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - final DisplayState state = getDisplayState(this); - final int id = item.getItemId(); - if (id == R.id.menu_grid) { - state.mode = DisplayState.MODE_GRID; - updateMode(); - getFragmentManager().invalidateOptionsMenu(); - return true; - } else if (id == R.id.menu_list) { - state.mode = DisplayState.MODE_LIST; - updateMode(); - getFragmentManager().invalidateOptionsMenu(); - return true; - } else { - return super.onOptionsItemSelected(item); - } - } - - private void updateMode() { - final DisplayState state = getDisplayState(this); + // TODO: avoid kicking loader when sort didn't change + getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks); + mListView.smoothScrollToPosition(0); + mGridView.smoothScrollToPosition(0); mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE); @@ -250,12 +227,6 @@ public class DirectoryFragment extends Fragment { } } - public void updateSortOrder() { - getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); - mListView.smoothScrollToPosition(0); - mGridView.smoothScrollToPosition(0); - } - private OnItemClickListener mItemListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @@ -309,7 +280,7 @@ public class DirectoryFragment extends Fragment { if (checked) { // Directories cannot be checked final Document doc = mAdapter.getItem(position); - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { + if (doc.isDirectory()) { mCurrentView.setItemChecked(position, false); } } @@ -337,10 +308,10 @@ public class DirectoryFragment extends Fragment { @Override public View getView(int position, View convertView, ViewGroup parent) { final Context context = parent.getContext(); + final DisplayState state = getDisplayState(DirectoryFragment.this); if (convertView == null) { final LayoutInflater inflater = LayoutInflater.from(context); - final DisplayState state = getDisplayState(DirectoryFragment.this); if (state.mode == DisplayState.MODE_LIST) { convertView = inflater.inflate(R.layout.item_doc_list, parent, false); } else if (state.mode == DisplayState.MODE_GRID) { @@ -352,9 +323,12 @@ public class DirectoryFragment extends Fragment { final Document doc = getItem(position); + final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); final TextView title = (TextView) convertView.findViewById(android.R.id.title); + final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1); final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); - final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); + final TextView date = (TextView) convertView.findViewById(R.id.date); + final TextView size = (TextView) convertView.findViewById(R.id.size); if (doc.isThumbnailSupported()) { // TODO: load thumbnails async @@ -365,8 +339,37 @@ public class DirectoryFragment extends Fragment { } title.setText(doc.displayName); - if (summary != null) { - summary.setText(DateUtils.getRelativeTimeSpanString(doc.lastModified)); + + if (mType == TYPE_NORMAL || mType == TYPE_SEARCH) { + icon1.setVisibility(View.GONE); + if (doc.summary != null) { + summary.setText(doc.summary); + summary.setVisibility(View.VISIBLE); + } else { + summary.setVisibility(View.INVISIBLE); + } + } else if (mType == TYPE_RECENT_OPEN) { + final Root root = RootsCache.findRoot(context, doc); + icon1.setVisibility(View.VISIBLE); + icon1.setImageDrawable(root.icon); + summary.setText(root.getDirectoryString()); + summary.setVisibility(View.VISIBLE); + } + + // TODO: omit year from format + date.setText(DateUtils.formatSameDayTime( + doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT, + DateFormat.SHORT)); + + if (state.showSize) { + size.setVisibility(View.VISIBLE); + if (doc.isDirectory()) { + size.setText(null); + } else { + size.setText(Formatter.formatFileSize(context, doc.size)); + } + } else { + size.setVisibility(View.GONE); } return convertView; diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 6067581869d1..6784d709dbbb 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -28,7 +28,6 @@ import android.database.Cursor; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; -import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; @@ -42,27 +41,23 @@ import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.SearchView; +import android.widget.SearchView.OnCloseListener; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import android.widget.Toast; import com.android.documentsui.model.Document; +import com.android.documentsui.model.DocumentStack; import com.android.documentsui.model.Root; -import org.json.JSONArray; -import org.json.JSONException; - import java.util.Arrays; -import java.util.LinkedList; import java.util.List; public class DocumentsActivity extends Activity { public static final String TAG = "Documents"; - // TODO: share backend root cache with recents provider - - private static final int ACTION_OPEN = 1; - private static final int ACTION_CREATE = 2; + public static final int ACTION_OPEN = 1; + public static final int ACTION_CREATE = 2; private int mAction; @@ -72,11 +67,12 @@ public class DocumentsActivity extends Activity { private DrawerLayout mDrawerLayout; private ActionBarDrawerToggle mDrawerToggle; - private Root mCurrentRoot; - private final DisplayState mDisplayState = new DisplayState(); - private LinkedList<Document> mStack = new LinkedList<Document>(); + /** Current user navigation stack; empty implies recents. */ + private DocumentStack mStack; + /** Currently active search, overriding any stack. */ + private String mCurrentSearch; @Override public void onCreate(Bundle icicle) { @@ -135,19 +131,14 @@ public class DocumentsActivity extends Activity { .query(RecentsProvider.buildResume(packageName), null, null, null, null); try { if (cursor.moveToFirst()) { - final String rawStack = cursor.getString( + final String raw = cursor.getString( cursor.getColumnIndex(RecentsProvider.COL_PATH)); - restoreStack(rawStack); + mStack = DocumentStack.deserialize(getContentResolver(), raw); } } finally { cursor.close(); } - // Start in recents if no restored stack - if (mStack.isEmpty()) { - onRootPicked(RootsCache.getRecentOpenRoot(this), false); - } - updateDirectoryFragment(); } @@ -201,7 +192,7 @@ public class DocumentsActivity extends Activity { final Root root = getCurrentRoot(); actionBar.setIcon(root != null ? root.icon : null); - if (getCurrentRoot().isRecents) { + if (root.isRecents) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); actionBar.setTitle(root.title); } else { @@ -229,10 +220,8 @@ public class DocumentsActivity extends Activity { mSearchView.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { - // TODO: use second directory stack for searches? - final Document cwd = getCurrentDirectory(); - final Document searchDoc = Document.fromSearch(cwd.uri, query); - onDocumentPicked(searchDoc); + mCurrentSearch = query; + updateDirectoryFragment(); mSearchView.setIconified(true); return true; } @@ -243,6 +232,15 @@ public class DocumentsActivity extends Activity { } }); + mSearchView.setOnCloseListener(new OnCloseListener() { + @Override + public boolean onClose() { + mCurrentSearch = null; + updateDirectoryFragment(); + return false; + } + }); + return true; } @@ -265,6 +263,9 @@ public class DocumentsActivity extends Activity { SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported()); } + menu.findItem(R.id.menu_grid).setVisible(mDisplayState.mode != DisplayState.MODE_GRID); + menu.findItem(R.id.menu_list).setVisible(mDisplayState.mode != DisplayState.MODE_LIST); + return true; } @@ -283,8 +284,19 @@ public class DocumentsActivity extends Activity { return true; } else if (id == R.id.menu_search) { return false; + } else if (id == R.id.menu_grid) { + mDisplayState.mode = DisplayState.MODE_GRID; + updateDisplayState(); + invalidateOptionsMenu(); + return true; + } else if (id == R.id.menu_list) { + mDisplayState.mode = DisplayState.MODE_LIST; + updateDisplayState(); + invalidateOptionsMenu(); + return true; + } else { + return super.onOptionsItemSelected(item); } - return super.onOptionsItemSelected(item); } @Override @@ -339,7 +351,8 @@ public class DocumentsActivity extends Activity { if (cwd != null) { title.setText(cwd.displayName); } else { - title.setText(null); + // No directory means recents + title.setText(R.string.root_recent); } summary.setText((String) getItem(position)); @@ -365,13 +378,18 @@ public class DocumentsActivity extends Activity { @Override public boolean onNavigationItemSelected(int itemPosition, long itemId) { mDisplayState.sortOrder = itemPosition; - DirectoryFragment.get(getFragmentManager()).updateSortOrder(); + updateDisplayState(); return true; } }; public Root getCurrentRoot() { - return mCurrentRoot; + final Document cwd = getCurrentDirectory(); + if (cwd != null) { + return RootsCache.findRoot(this, cwd); + } else { + return RootsCache.getRecentsRoot(this); + } } public Document getCurrentDirectory() { @@ -385,19 +403,47 @@ public class DocumentsActivity extends Activity { private void updateDirectoryFragment() { final FragmentManager fm = getFragmentManager(); final Document cwd = getCurrentDirectory(); - if (cwd != null) { - DirectoryFragment.show(fm, cwd.uri); + if (cwd == null) { + // No directory means recents + if (mAction == ACTION_CREATE) { + RecentsCreateFragment.show(fm); + } else { + DirectoryFragment.showRecentsOpen(fm); + } + } else { + if (mCurrentSearch != null) { + // Ongoing search + DirectoryFragment.showSearch(fm, cwd.uri, mCurrentSearch); + } else { + // Normal boring directory + DirectoryFragment.showNormal(fm, cwd.uri); + } } + updateActionBar(); invalidateOptionsMenu(); dumpStack(); } + private void updateDisplayState() { + // TODO: handle multiple directory stacks on tablets + DirectoryFragment.get(getFragmentManager()).updateDisplayState(); + } + + public void onStackPicked(DocumentStack stack) { + mStack = stack; + updateDirectoryFragment(); + } + public void onRootPicked(Root root, boolean closeDrawer) { // Clear entire backstack and start in new root mStack.clear(); - mCurrentRoot = root; - onDocumentPicked(Document.fromRoot(getContentResolver(), root)); + + if (!root.isRecents) { + onDocumentPicked(Document.fromRoot(getContentResolver(), root)); + } else { + updateDirectoryFragment(); + } if (closeDrawer) { mDrawerLayout.closeDrawers(); @@ -406,7 +452,7 @@ public class DocumentsActivity extends Activity { public void onDocumentPicked(Document doc) { final FragmentManager fm = getFragmentManager(); - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { + if (doc.isDirectory()) { mStack.push(doc); updateDirectoryFragment(); } else if (mAction == ACTION_OPEN) { @@ -443,52 +489,17 @@ public class DocumentsActivity extends Activity { } } - private String saveStack() { - if (mCurrentRoot.isRecents) return null; - - final JSONArray stack = new JSONArray(); - for (int i = 0; i < mStack.size(); i++) { - stack.put(mStack.get(i).uri); - } - return stack.toString(); - } - - private void restoreStack(String rawStack) { - Log.d(TAG, "restoreStack: " + rawStack); - mStack.clear(); - - if (rawStack == null) return; - try { - final JSONArray stack = new JSONArray(rawStack); - for (int i = 0; i < stack.length(); i++) { - final Uri uri = Uri.parse(stack.getString(i)); - final Document doc = Document.fromUri(getContentResolver(), uri); - mStack.add(doc); - } - } catch (JSONException e) { - Log.w(TAG, "Failed to decode stack", e); - } - - // TODO: handle roots that have gone missing - final Document cwd = getCurrentDirectory(); - if (cwd != null) { - final String authority = cwd.uri.getAuthority(); - final String rootId = DocumentsContract.getRootId(cwd.uri); - mCurrentRoot = RootsCache.findRoot(this, authority, rootId); - } - } - private void onFinished(Uri... uris) { Log.d(TAG, "onFinished() " + Arrays.toString(uris)); final ContentResolver resolver = getContentResolver(); final ContentValues values = new ContentValues(); - final String stack = saveStack(); + final String rawStack = DocumentStack.serialize(mStack); if (mAction == ACTION_CREATE) { // Remember stack for last create values.clear(); - values.put(RecentsProvider.COL_PATH, stack); + values.put(RecentsProvider.COL_PATH, rawStack); resolver.insert(RecentsProvider.buildRecentCreate(), values); } else if (mAction == ACTION_OPEN) { @@ -503,7 +514,7 @@ public class DocumentsActivity extends Activity { // Remember location for next app launch final String packageName = getCallingPackage(); values.clear(); - values.put(RecentsProvider.COL_PATH, stack); + values.put(RecentsProvider.COL_PATH, rawStack); resolver.insert(RecentsProvider.buildResume(packageName), values); final Intent intent = new Intent(); @@ -532,6 +543,7 @@ public class DocumentsActivity extends Activity { public String[] acceptMimes; public int sortOrder = SORT_ORDER_NAME; public boolean allowMultiple = false; + public boolean showSize = false; public static final int MODE_LIST = 0; public static final int MODE_GRID = 1; diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java index 0d2f381dd2bf..f945c6a0d98c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java +++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java @@ -16,8 +16,6 @@ package com.android.documentsui; -import android.provider.DocumentsContract; - import com.android.documentsui.model.Document; import com.android.internal.util.Predicate; @@ -30,7 +28,7 @@ public class MimePredicate implements Predicate<Document> { @Override public boolean apply(Document doc) { - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { + if (doc.isDirectory()) { return true; } for (String filter : mFilters) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java new file mode 100644 index 000000000000..2651e4c358a3 --- /dev/null +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2013 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. + */ + +package com.android.documentsui; + +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.app.LoaderManager.LoaderCallbacks; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Loader; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.text.TextUtils.TruncateAt; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.android.documentsui.model.DocumentStack; +import com.android.documentsui.model.Root; +import com.google.android.collect.Lists; + +import libcore.io.IoUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Display directories where recent creates took place. + */ +public class RecentsCreateFragment extends Fragment { + + private ListView mListView; + + private DocumentStackAdapter mAdapter; + private LoaderCallbacks<List<DocumentStack>> mCallbacks; + + private static final int LOADER_RECENTS = 3; + + public static void show(FragmentManager fm) { + final RecentsCreateFragment fragment = new RecentsCreateFragment(); + final FragmentTransaction ft = fm.beginTransaction(); + ft.replace(R.id.container_directory, fragment); + ft.commitAllowingStateLoss(); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final Context context = inflater.getContext(); + + final View view = inflater.inflate(R.layout.fragment_directory, container, false); + + mListView = (ListView) view.findViewById(R.id.list); + mListView.setOnItemClickListener(mItemListener); + + mAdapter = new DocumentStackAdapter(); + mListView.setAdapter(mAdapter); + + mCallbacks = new LoaderCallbacks<List<DocumentStack>>() { + @Override + public Loader<List<DocumentStack>> onCreateLoader(int id, Bundle args) { + return new RecentsCreateLoader(context); + } + + @Override + public void onLoadFinished( + Loader<List<DocumentStack>> loader, List<DocumentStack> data) { + mAdapter.swapStacks(data); + } + + @Override + public void onLoaderReset(Loader<List<DocumentStack>> loader) { + mAdapter.swapStacks(null); + } + }; + + return view; + } + + @Override + public void onStart() { + super.onStart(); + getLoaderManager().restartLoader(LOADER_RECENTS, getArguments(), mCallbacks); + } + + @Override + public void onStop() { + super.onStop(); + getLoaderManager().destroyLoader(LOADER_RECENTS); + } + + private OnItemClickListener mItemListener = new OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + final DocumentStack stack = mAdapter.getItem(position); + ((DocumentsActivity) getActivity()).onStackPicked(stack); + } + }; + + public static class RecentsCreateLoader extends UriDerivativeLoader<List<DocumentStack>> { + public RecentsCreateLoader(Context context) { + super(context, RecentsProvider.buildRecentCreate()); + } + + @Override + public List<DocumentStack> loadInBackground(Uri uri, CancellationSignal signal) { + final ArrayList<DocumentStack> result = Lists.newArrayList(); + + final ContentResolver resolver = getContext().getContentResolver(); + final Cursor cursor = resolver.query( + uri, null, null, null, RecentsProvider.COL_TIMESTAMP + " DESC", signal); + try { + while (cursor != null && cursor.moveToNext()) { + final String rawStack = cursor.getString( + cursor.getColumnIndex(RecentsProvider.COL_PATH)); + final DocumentStack stack = DocumentStack.deserialize(resolver, rawStack); + result.add(stack); + } + } finally { + IoUtils.closeQuietly(cursor); + } + + return result; + } + } + + private class DocumentStackAdapter extends BaseAdapter { + private List<DocumentStack> mStacks; + + public DocumentStackAdapter() { + } + + public void swapStacks(List<DocumentStack> stacks) { + mStacks = stacks; + notifyDataSetChanged(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final Context context = parent.getContext(); + + if (convertView == null) { + final LayoutInflater inflater = LayoutInflater.from(context); + convertView = inflater.inflate(R.layout.item_doc_list, parent, false); + } + + final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); + final TextView title = (TextView) convertView.findViewById(android.R.id.title); + final View line2 = convertView.findViewById(R.id.line2); + + final DocumentStack stack = getItem(position); + final Root root = RootsCache.findRoot(context, stack.peek()); + icon.setImageDrawable(root != null ? root.icon : null); + + final StringBuilder builder = new StringBuilder(); + final int size = stack.size(); + for (int i = 0; i < size; i++) { + builder.append(stack.get(i).displayName); + if (i < size - 1) { + builder.append(" \u232a "); + } + } + title.setText(builder.toString()); + title.setEllipsize(TruncateAt.MIDDLE); + + line2.setVisibility(View.GONE); + + return convertView; + } + + @Override + public int getCount() { + return mStacks != null ? mStacks.size() : 0; + } + + @Override + public DocumentStack getItem(int position) { + return mStacks.get(position); + } + + @Override + public long getItemId(int position) { + return getItem(position).hashCode(); + } + } +} diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java index dbcb0396fdc4..5268c1d25c3d 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java @@ -129,11 +129,11 @@ public class RecentsProvider extends ContentProvider { switch (sMatcher.match(uri)) { case URI_RECENT_OPEN: { return db.query(TABLE_RECENT_OPEN, projection, - buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null); + buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder); } case URI_RECENT_CREATE: { return db.query(TABLE_RECENT_CREATE, projection, - buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null); + buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder); } case URI_RESUME: { final String packageName = uri.getPathSegments().get(1); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 1b56a2003157..b26db3ba4153 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -30,6 +30,7 @@ import android.provider.DocumentsContract; import android.util.Log; import android.util.Pair; +import com.android.documentsui.model.Document; import com.android.documentsui.model.DocumentsProviderInfo; import com.android.documentsui.model.DocumentsProviderInfo.Icon; import com.android.documentsui.model.Root; @@ -58,7 +59,7 @@ public class RootsCache { public static ArrayList<Root> sRootsList = Lists.newArrayList(); - private static Root sRecentOpenRoot; + private static Root sRecentsRoot; /** * Gather roots from all known storage providers. @@ -73,9 +74,9 @@ public class RootsCache { { // Create special root for recents - final Root root = Root.buildRecentOpen(context); + final Root root = Root.buildRecents(context); sRootsList.add(root); - sRecentOpenRoot = root; + sRecentsRoot = root; } // Query for other storage backends @@ -125,13 +126,21 @@ public class RootsCache { } @GuardedBy("ActivityThread") - public static Root getRecentOpenRoot(Context context) { + public static Root findRoot(Context context, Document doc) { + final String authority = doc.uri.getAuthority(); + final String rootId = DocumentsContract.getRootId(doc.uri); + return findRoot(context, authority, rootId); + } + + @GuardedBy("ActivityThread") + public static Root getRecentsRoot(Context context) { ensureCache(context); - return sRecentOpenRoot; + return sRecentsRoot; } @GuardedBy("ActivityThread") - public static Collection<Root> getRoots() { + public static Collection<Root> getRoots(Context context) { + ensureCache(context); return sRootsList; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index 3e645bcb6241..c4e9c15aa686 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -69,7 +69,7 @@ public class RootsFragment extends Fragment { final View view = inflater.inflate(R.layout.fragment_roots, container, false); mList = (ListView) view.findViewById(android.R.id.list); - mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots()); + mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots(context)); mList.setAdapter(mAdapter); mList.setOnItemClickListener(mItemListener); diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java index ed69690010f3..3b82ba8c4b17 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java @@ -35,26 +35,22 @@ public class Document { public final String displayName; public final long lastModified; public final int flags; + public final String summary; + public final long size; - private Document(Uri uri, String mimeType, String displayName, long lastModified, int flags) { + private Document(Uri uri, String mimeType, String displayName, long lastModified, int flags, + String summary, long size) { this.uri = uri; this.mimeType = mimeType; this.displayName = displayName; this.lastModified = lastModified; this.flags = flags; + this.summary = summary; + this.size = size; } public static Document fromRoot(ContentResolver resolver, Root root) { - if (root.isRecents) { - final Uri uri = root.uri; - final String mimeType = DocumentsContract.MIME_TYPE_DIRECTORY; - final String displayName = root.title; - final long lastModified = -1; - final int flags = 0; - return new Document(uri, mimeType, displayName, lastModified, flags); - } else { - return fromUri(resolver, root.uri); - } + return fromUri(resolver, root.uri); } public static Document fromDirectoryCursor(Uri parent, Cursor cursor) { @@ -67,8 +63,10 @@ public class Document { final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); + final String summary = getCursorString(cursor, DocumentColumns.SUMMARY); + final long size = getCursorLong(cursor, DocumentColumns.SIZE); - return new Document(uri, mimeType, displayName, lastModified, flags); + return new Document(uri, mimeType, displayName, lastModified, flags, summary, size); } public static Document fromRecentOpenCursor(ContentResolver resolver, Cursor cursor) { @@ -84,8 +82,10 @@ public class Document { final String displayName = getCursorString(itemCursor, DocumentColumns.DISPLAY_NAME); final int flags = getCursorInt(itemCursor, DocumentColumns.FLAGS) & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL; + final String summary = getCursorString(cursor, DocumentColumns.SUMMARY); + final long size = getCursorLong(cursor, DocumentColumns.SIZE); - return new Document(uri, mimeType, displayName, lastModified, flags); + return new Document(uri, mimeType, displayName, lastModified, flags, summary, size); } finally { itemCursor.close(); } @@ -101,22 +101,15 @@ public class Document { final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); + final String summary = getCursorString(cursor, DocumentColumns.SUMMARY); + final long size = getCursorLong(cursor, DocumentColumns.SIZE); - return new Document(uri, mimeType, displayName, lastModified, flags); + return new Document(uri, mimeType, displayName, lastModified, flags, summary, size); } finally { cursor.close(); } } - public static Document fromSearch(Uri relatedUri, String query) { - final Uri uri = DocumentsContract.buildSearchUri(relatedUri, query); - final String mimeType = DocumentsContract.MIME_TYPE_DIRECTORY; - final String displayName = query; - final long lastModified = System.currentTimeMillis(); - final int flags = 0; - return new Document(uri, mimeType, displayName, lastModified, flags); - } - @Override public String toString() { return "Document{name=" + displayName + ", uri=" + uri + "}"; @@ -134,23 +127,30 @@ public class Document { return (flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0; } + public boolean isDirectory() { + return DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType); + } + private static String getCursorString(Cursor cursor, String columnName) { - return cursor.getString(cursor.getColumnIndexOrThrow(columnName)); + final int index = cursor.getColumnIndex(columnName); + return (index != -1) ? cursor.getString(index) : null; } private static long getCursorLong(Cursor cursor, String columnName) { - return cursor.getLong(cursor.getColumnIndexOrThrow(columnName)); + final int index = cursor.getColumnIndex(columnName); + return (index != -1) ? cursor.getLong(index) : 0; } private static int getCursorInt(Cursor cursor, String columnName) { - return cursor.getInt(cursor.getColumnIndexOrThrow(columnName)); + final int index = cursor.getColumnIndex(columnName); + return (index != -1) ? cursor.getInt(index) : 0; } public static class NameComparator implements Comparator<Document> { @Override public int compare(Document lhs, Document rhs) { - final boolean leftDir = DocumentsContract.MIME_TYPE_DIRECTORY.equals(lhs.mimeType); - final boolean rightDir = DocumentsContract.MIME_TYPE_DIRECTORY.equals(rhs.mimeType); + final boolean leftDir = lhs.isDirectory(); + final boolean rightDir = rhs.isDirectory(); if (leftDir != rightDir) { return leftDir ? -1 : 1; diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java new file mode 100644 index 000000000000..dade8a357b97 --- /dev/null +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 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. + */ + +package com.android.documentsui.model; + +import static com.android.documentsui.DocumentsActivity.TAG; + +import android.content.ContentResolver; +import android.net.Uri; +import android.util.Log; + +import org.json.JSONArray; +import org.json.JSONException; + +import java.util.LinkedList; + +/** + * Representation of a stack of {@link Document}, usually the result of a + * user-driven traversal. + */ +public class DocumentStack extends LinkedList<Document> { + + public static String serialize(DocumentStack stack) { + final JSONArray json = new JSONArray(); + for (int i = 0; i < stack.size(); i++) { + json.put(stack.get(i).uri); + } + return json.toString(); + } + + public static DocumentStack deserialize(ContentResolver resolver, String raw) { + Log.d(TAG, "restoreStack: " + raw); + + final DocumentStack stack = new DocumentStack(); + try { + final JSONArray json = new JSONArray(raw); + for (int i = 0; i < json.length(); i++) { + final Uri uri = Uri.parse(json.getString(i)); + final Document doc = Document.fromUri(resolver, uri); + stack.add(doc); + } + } catch (JSONException e) { + Log.w(TAG, "Failed to decode stack", e); + } + + // TODO: handle roots that have gone missing + return stack; + } +} diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java index 9d816d7ace79..629dbc4d8b72 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java @@ -43,12 +43,12 @@ public class Root { public String summary; public boolean isRecents; - public static Root buildRecentOpen(Context context) { + public static Root buildRecents(Context context) { final PackageManager pm = context.getPackageManager(); final Root root = new Root(); root.rootId = null; root.rootType = DocumentsContract.ROOT_TYPE_SHORTCUT; - root.uri = RecentsProvider.buildRecentOpen(); + root.uri = null; root.icon = context.getResources().getDrawable(R.drawable.ic_dir); root.title = context.getString(R.string.root_recent); root.summary = null; @@ -92,6 +92,13 @@ public class Root { return root; } + /** + * Return string most suited to showing in a directory listing. + */ + public String getDirectoryString() { + return (summary != null) ? summary : title; + } + public static class RootComparator implements Comparator<Root> { @Override public int compare(Root lhs, Root rhs) { |