diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-08-07 16:22:02 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-08-07 16:29:51 -0700 |
commit | 9fb567b59112f99e64e0bff6f343188331bad28d (patch) | |
tree | 75be88e422f398bf0b3f5d42bd0dc42a077bdd69 | |
parent | b156f4bf8cdfe475a7116b627d84a281e1a281b7 (diff) | |
download | frameworks_base-9fb567b59112f99e64e0bff6f343188331bad28d.zip frameworks_base-9fb567b59112f99e64e0bff6f343188331bad28d.tar.gz frameworks_base-9fb567b59112f99e64e0bff6f343188331bad28d.tar.bz2 |
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
18 files changed, 330 insertions, 61 deletions
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 289531e..acaed73 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -105,6 +105,8 @@ public final class DocumentsContract { */ public static final int FLAG_SUPPORTS_SEARCH = 1 << 4; + // TODO: flag indicating that document is writable? + /** * Optimal dimensions for a document thumbnail request, stored as a * {@link Point} object. This is only a hint, and the returned thumbnail may diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 1d97161..27f93c0 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -7,11 +7,13 @@ android:label="@string/app_label" android:supportsRtl="true"> + <!-- TODO: allow rotation when state saving is in better shape --> <activity android:name=".DocumentsActivity" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" - android:theme="@android:style/Theme.Holo.Light"> + android:theme="@android:style/Theme.Holo.Light" + android:screenOrientation="nosensor"> <intent-filter android:priority="100"> <action android:name="android.intent.action.OPEN_DOCUMENT" /> <category android:name="android.intent.category.DEFAULT" /> @@ -24,6 +26,12 @@ </intent-filter> </activity> + <activity + android:name=".SettingsActivity" + android:title="@string/menu_settings" + android:theme="@android:style/Theme.Holo.Light" + android:exported="false" /> + <provider android:name=".RecentsProvider" android:authorities="com.android.documentsui.recents" diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml index 638ac92..8dbd1de 100644 --- a/packages/DocumentsUI/res/layout/fragment_directory.xml +++ b/packages/DocumentsUI/res/layout/fragment_directory.xml @@ -18,6 +18,15 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + <TextView + android:id="@android:id/empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:text="@string/empty" + android:textAppearance="?android:attr/textAppearanceMedium" + android:visibility="gone" /> + <ListView android:id="@+id/list" android:layout_width="match_parent" @@ -30,6 +39,7 @@ android:layout_height="match_parent" android:listSelector="@android:color/transparent" android:paddingTop="?android:attr/listPreferredItemPaddingStart" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" /> + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:visibility="gone" /> </FrameLayout> diff --git a/packages/DocumentsUI/res/layout/fragment_save.xml b/packages/DocumentsUI/res/layout/fragment_save.xml index 85c48b1..49038bc 100644 --- a/packages/DocumentsUI/res/layout/fragment_save.xml +++ b/packages/DocumentsUI/res/layout/fragment_save.xml @@ -36,7 +36,8 @@ android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" - android:singleLine="true" /> + android:singleLine="true" + android:selectAllOnFocus="true" /> <Button android:id="@android:id/button1" diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml index ad8f51c..244214b 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="160dip" + android:layout_height="180dip" android:paddingBottom="?android:attr/listPreferredItemPaddingEnd" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> @@ -30,6 +30,7 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingBottom="6dp" android:orientation="vertical"> <ImageView @@ -54,10 +55,10 @@ android:textAlignment="viewStart" /> <LinearLayout + android:id="@+id/summary_grid" 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"> @@ -75,12 +76,25 @@ 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" /> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + <View + android:layout_width="0dip" + android:layout_height="0dip" + android:layout_weight="1" /> + <TextView android:id="@+id/size" android:layout_width="70dp" diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml index bb27173..37c5881 100644 --- a/packages/DocumentsUI/res/layout/item_doc_list.xml +++ b/packages/DocumentsUI/res/layout/item_doc_list.xml @@ -51,7 +51,7 @@ android:textAlignment="viewStart" /> <LinearLayout - android:id="@+id/line2" + android:id="@+id/summary_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml index d57f88a..575336c 100644 --- a/packages/DocumentsUI/res/menu/activity.xml +++ b/packages/DocumentsUI/res/menu/activity.xml @@ -37,4 +37,8 @@ android:title="@string/menu_list" android:icon="@drawable/ic_menu_list" android:showAsAction="ifRoom" /> + <item + android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:showAsAction="never" /> </menu> diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml index 2ff5d03..84f89b4 100644 --- a/packages/DocumentsUI/res/values/strings.xml +++ b/packages/DocumentsUI/res/values/strings.xml @@ -25,6 +25,7 @@ <string name="menu_list">List view</string> <string name="menu_sort">Sort by</string> <string name="menu_search">Search</string> + <string name="menu_settings">Settings</string> <string name="menu_open">Open</string> <string name="menu_save">Save</string> @@ -33,6 +34,7 @@ <string name="sort_name">By name</string> <string name="sort_date">By date modified</string> + <string name="sort_size">By size</string> <string name="drawer_open">Show roots</string> <string name="drawer_close">Hide roots</string> @@ -40,9 +42,16 @@ <string name="save_error">Failed to save document</string> <string name="root_recent">Recent</string> + <string name="root_available_bytes"><xliff:g id="size" example="3GB">%1$s</xliff:g> free</string> <string name="root_type_service">Services</string> <string name="root_type_shortcut">Shortcuts</string> <string name="root_type_device">Devices</string> + <string name="pref_advanced_devices">Display advanced devices</string> + <string name="pref_file_size">Display file size</string> + <string name="pref_device_size">Display device size</string> + + <string name="empty">No items</string> + </resources> diff --git a/packages/DocumentsUI/res/xml/preferences.xml b/packages/DocumentsUI/res/xml/preferences.xml new file mode 100644 index 0000000..5589ff1 --- /dev/null +++ b/packages/DocumentsUI/res/xml/preferences.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <CheckBoxPreference + android:title="@string/pref_advanced_devices" + android:defaultValue="false" + android:key="advancedDevices" /> + <CheckBoxPreference + android:title="@string/pref_file_size" + android:defaultValue="false" + android:key="fileSize" /> +</PreferenceScreen> diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index d986a51..5a6060a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -27,7 +27,6 @@ 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; @@ -62,11 +61,14 @@ import java.util.concurrent.atomic.AtomicInteger; */ 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 @@ public class DirectoryFragment extends Fragment { 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 @@ public class DirectoryFragment extends Fragment { @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 @@ public class DirectoryFragment extends Fragment { 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 @@ public class DirectoryFragment extends Fragment { @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 class DirectoryFragment extends Fragment { 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 class DirectoryFragment extends Fragment { 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 @@ public class DirectoryFragment extends Fragment { 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 @@ public class DirectoryFragment extends Fragment { 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 class DirectoryFragment extends Fragment { 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); + } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 6784d709d..fae5673 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -19,15 +19,18 @@ package com.android.documentsui; import android.app.ActionBar; import android.app.ActionBar.OnNavigationListener; import android.app.Activity; +import android.app.Fragment; import android.app.FragmentManager; import android.content.ClipData; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; +import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; import android.provider.DocumentsContract.DocumentColumns; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; @@ -139,7 +142,7 @@ public class DocumentsActivity extends Activity { cursor.close(); } - updateDirectoryFragment(); + onCurrentDirectoryChanged(); } private DrawerListener mDrawerListener = new DrawerListener() { @@ -221,7 +224,7 @@ public class DocumentsActivity extends Activity { @Override public boolean onQueryTextSubmit(String query) { mCurrentSearch = query; - updateDirectoryFragment(); + onCurrentDirectoryChanged(); mSearchView.setIconified(true); return true; } @@ -236,7 +239,7 @@ public class DocumentsActivity extends Activity { @Override public boolean onClose() { mCurrentSearch = null; - updateDirectoryFragment(); + onCurrentDirectoryChanged(); return false; } }); @@ -248,23 +251,36 @@ public class DocumentsActivity extends Activity { public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); + final FragmentManager fm = getFragmentManager(); final Document cwd = getCurrentDirectory(); final MenuItem createDir = menu.findItem(R.id.menu_create_dir); - createDir.setVisible(mAction == ACTION_CREATE); - createDir.setEnabled(cwd != null && cwd.isCreateSupported()); - - // TODO: close any search in-progress when hiding final MenuItem search = menu.findItem(R.id.menu_search); - search.setVisible(cwd != null && cwd.isSearchSupported()); + final MenuItem grid = menu.findItem(R.id.menu_grid); + final MenuItem list = menu.findItem(R.id.menu_list); + grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID); + list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST); + + final boolean searchVisible; if (mAction == ACTION_CREATE) { - final FragmentManager fm = getFragmentManager(); + createDir.setVisible(cwd != null && cwd.isCreateSupported()); + searchVisible = false; + + // No display options in recent directories + if (cwd == null) { + grid.setVisible(false); + list.setVisible(false); + } + SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported()); + } else { + createDir.setVisible(false); + searchVisible = cwd != null && cwd.isSearchSupported(); } - menu.findItem(R.id.menu_grid).setVisible(mDisplayState.mode != DisplayState.MODE_GRID); - menu.findItem(R.id.menu_list).setVisible(mDisplayState.mode != DisplayState.MODE_LIST); + // TODO: close any search in-progress when hiding + search.setVisible(searchVisible); return true; } @@ -294,6 +310,9 @@ public class DocumentsActivity extends Activity { updateDisplayState(); invalidateOptionsMenu(); return true; + } else if (id == R.id.menu_settings) { + startActivity(new Intent(this, SettingsActivity.class)); + return true; } else { return super.onOptionsItemSelected(item); } @@ -304,7 +323,7 @@ public class DocumentsActivity extends Activity { final int size = mStack.size(); if (size > 1) { mStack.pop(); - updateDirectoryFragment(); + onCurrentDirectoryChanged(); } else if (size == 1 && !mDrawerLayout.isDrawerOpen(mRootsContainer)) { // TODO: open root drawer once we can capture back key super.onBackPressed(); @@ -317,7 +336,7 @@ public class DocumentsActivity extends Activity { private BaseAdapter mSortAdapter = new BaseAdapter() { @Override public int getCount() { - return 2; + return mDisplayState.showSize ? 3 : 2; } @Override @@ -327,6 +346,8 @@ public class DocumentsActivity extends Activity { return getText(R.string.sort_name); case 1: return getText(R.string.sort_date); + case 2: + return getText(R.string.sort_size); default: return null; } @@ -400,9 +421,10 @@ public class DocumentsActivity extends Activity { return mDisplayState; } - private void updateDirectoryFragment() { + private void onCurrentDirectoryChanged() { final FragmentManager fm = getFragmentManager(); final Document cwd = getCurrentDirectory(); + if (cwd == null) { // No directory means recents if (mAction == ACTION_CREATE) { @@ -420,6 +442,14 @@ public class DocumentsActivity extends Activity { } } + // Forget any replacement target + if (mAction == ACTION_CREATE) { + final SaveFragment save = SaveFragment.get(fm); + if (save != null) { + save.setReplaceTarget(null); + } + } + updateActionBar(); invalidateOptionsMenu(); dumpStack(); @@ -432,7 +462,7 @@ public class DocumentsActivity extends Activity { public void onStackPicked(DocumentStack stack) { mStack = stack; - updateDirectoryFragment(); + onCurrentDirectoryChanged(); } public void onRootPicked(Root root, boolean closeDrawer) { @@ -442,7 +472,7 @@ public class DocumentsActivity extends Activity { if (!root.isRecents) { onDocumentPicked(Document.fromRoot(getContentResolver(), root)); } else { - updateDirectoryFragment(); + onCurrentDirectoryChanged(); } if (closeDrawer) { @@ -454,13 +484,13 @@ public class DocumentsActivity extends Activity { final FragmentManager fm = getFragmentManager(); if (doc.isDirectory()) { mStack.push(doc); - updateDirectoryFragment(); + onCurrentDirectoryChanged(); } else if (mAction == ACTION_OPEN) { // Explicit file picked, return onFinished(doc.uri); } else if (mAction == ACTION_CREATE) { - // Overwrite current filename - SaveFragment.get(fm).setDisplayName(doc.displayName); + // Replace selected file + SaveFragment.get(fm).setReplaceTarget(doc); } } @@ -473,9 +503,11 @@ public class DocumentsActivity extends Activity { onFinished(uris); } - public void onSaveRequested(String mimeType, String displayName) { - // TODO: handle overwrite by using last-selected GUID + public void onSaveRequested(Document replaceTarget) { + onFinished(replaceTarget.uri); + } + public void onSaveRequested(String mimeType, String displayName) { final ContentValues values = new ContentValues(); values.put(DocumentColumns.MIME_TYPE, mimeType); values.put(DocumentColumns.DISPLAY_NAME, displayName); @@ -550,6 +582,7 @@ public class DocumentsActivity extends Activity { public static final int SORT_ORDER_NAME = 0; public static final int SORT_ORDER_DATE = 1; + public static final int SORT_ORDER_SIZE = 2; } private void dumpStack() { @@ -558,4 +591,8 @@ public class DocumentsActivity extends Activity { Log.d(TAG, "--> " + doc); } } + + public static DocumentsActivity get(Fragment fragment) { + return (DocumentsActivity) fragment.getActivity(); + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java index 2651e4c..1e018e7 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java @@ -169,24 +169,23 @@ public class RecentsCreateFragment extends Fragment { 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 View summaryList = convertView.findViewById(R.id.summary_list); 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++) { + for (int i = stack.size() - 1; i >= 0; i--) { builder.append(stack.get(i).displayName); - if (i < size - 1) { + if (i > 0) { builder.append(" \u232a "); } } title.setText(builder.toString()); title.setEllipsize(TruncateAt.MIDDLE); - line2.setVisibility(View.GONE); + summaryList.setVisibility(View.GONE); return convertView; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index c4e9c15..427ad42 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -24,6 +24,7 @@ import android.app.FragmentTransaction; import android.content.Context; import android.os.Bundle; import android.provider.DocumentsContract; +import android.text.format.Formatter; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -76,6 +77,14 @@ public class RootsFragment extends Fragment { return view; } + @Override + public void onStart() { + super.onStart(); + + final Context context = getActivity(); + mAdapter.setShowAdvanced(SettingsActivity.getDisplayAdvancedDevices(context)); + } + private OnItemClickListener mItemListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @@ -94,8 +103,9 @@ public class RootsFragment extends Fragment { @Override public View getView(int position, View convertView, ViewGroup parent) { + final Context context = parent.getContext(); if (convertView == null) { - convertView = LayoutInflater.from(parent.getContext()) + convertView = LayoutInflater.from(context) .inflate(R.layout.item_root, parent, false); } @@ -107,8 +117,19 @@ public class RootsFragment extends Fragment { icon.setImageDrawable(root.icon); title.setText(root.title); - summary.setText(root.summary); - summary.setVisibility(root.summary != null ? View.VISIBLE : View.GONE); + // Device summary is always available space + final String summaryText; + if ((root.rootType == DocumentsContract.ROOT_TYPE_DEVICE + || root.rootType == DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED) + && root.availableBytes >= 0) { + summaryText = context.getString(R.string.root_available_bytes, + Formatter.formatFileSize(context, root.availableBytes)); + } else { + summaryText = root.summary; + } + + summary.setText(summaryText); + summary.setVisibility(summaryText != null ? View.VISIBLE : View.GONE); return convertView; } @@ -163,9 +184,6 @@ public class RootsFragment extends Fragment { mShortcuts.sort(comp); mDevices.sort(comp); mDevicesAdvanced.sort(comp); - - // TODO: switch to hide advanced items by default - setShowAdvanced(true); } public void setShowAdvanced(boolean showAdvanced) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java index 304f6e3..69010dd 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java @@ -21,6 +21,9 @@ import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Context; import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -28,14 +31,18 @@ import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; +import com.android.documentsui.model.Document; + /** * Display document title editor and save button. */ public class SaveFragment extends Fragment { public static final String TAG = "SaveFragment"; + private Document mReplaceTarget; private EditText mDisplayName; private Button mSave; + private boolean mIgnoreNextEdit; private static final String EXTRA_MIME_TYPE = "mime_type"; private static final String EXTRA_DISPLAY_NAME = "display_name"; @@ -69,6 +76,7 @@ public class SaveFragment extends Fragment { context, null, getArguments().getString(EXTRA_MIME_TYPE))); mDisplayName = (EditText) view.findViewById(android.R.id.title); + mDisplayName.addTextChangedListener(mDisplayNameWatcher); mDisplayName.setText(getArguments().getString(EXTRA_DISPLAY_NAME)); mSave = (Button) view.findViewById(android.R.id.button1); @@ -78,18 +86,55 @@ public class SaveFragment extends Fragment { return view; } + private TextWatcher mDisplayNameWatcher = new TextWatcher() { + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (mIgnoreNextEdit) { + mIgnoreNextEdit = false; + } else { + Log.d(TAG, "onTextChanged!"); + mReplaceTarget = null; + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // ignored + } + + @Override + public void afterTextChanged(Editable s) { + // ignored + } + }; + private View.OnClickListener mSaveListener = new View.OnClickListener() { @Override public void onClick(View v) { - final String mimeType = getArguments().getString(EXTRA_MIME_TYPE); - final String displayName = mDisplayName.getText().toString(); - ((DocumentsActivity) getActivity()).onSaveRequested(mimeType, displayName); + final DocumentsActivity activity = DocumentsActivity.get(SaveFragment.this); + if (mReplaceTarget != null) { + activity.onSaveRequested(mReplaceTarget); + } else { + final String mimeType = getArguments().getString(EXTRA_MIME_TYPE); + final String displayName = mDisplayName.getText().toString(); + activity.onSaveRequested(mimeType, displayName); + } } }; - public void setDisplayName(String displayName) { - getArguments().putString(EXTRA_DISPLAY_NAME, displayName); - mDisplayName.setText(displayName); + /** + * Set given document as target for in-place writing if user hits save + * without changing the filename. Can be set to {@code null} if user + * navigates outside the target directory. + */ + public void setReplaceTarget(Document replaceTarget) { + mReplaceTarget = replaceTarget; + + if (mReplaceTarget != null) { + getArguments().putString(EXTRA_DISPLAY_NAME, replaceTarget.displayName); + mIgnoreNextEdit = true; + mDisplayName.setText(replaceTarget.displayName); + } } public void setSaveEnabled(boolean enabled) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/SettingsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/SettingsActivity.java new file mode 100644 index 0000000..ceeaaae --- /dev/null +++ b/packages/DocumentsUI/src/com/android/documentsui/SettingsActivity.java @@ -0,0 +1,53 @@ +/* + * 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.Activity; +import android.content.Context; +import android.os.Bundle; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; + +public class SettingsActivity extends Activity { + private static final String KEY_ADVANCED_DEVICES = "advancedDevices"; + private static final String KEY_FILE_SIZE = "fileSize"; + + public static boolean getDisplayAdvancedDevices(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(KEY_ADVANCED_DEVICES, false); + } + + public static boolean getDisplayFileSize(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(KEY_FILE_SIZE, false); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getFragmentManager() + .beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); + } + + public static class SettingsFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } + } +} diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java index 3b82ba8..f274465 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.util.Log; import com.android.documentsui.RecentsProvider; @@ -69,25 +70,25 @@ public class Document { return new Document(uri, mimeType, displayName, lastModified, flags, summary, size); } - public static Document fromRecentOpenCursor(ContentResolver resolver, Cursor cursor) { - final Uri uri = Uri.parse(getCursorString(cursor, RecentsProvider.COL_URI)); - final long lastModified = getCursorLong(cursor, RecentsProvider.COL_TIMESTAMP); + public static Document fromRecentOpenCursor(ContentResolver resolver, Cursor recentCursor) { + final Uri uri = Uri.parse(getCursorString(recentCursor, RecentsProvider.COL_URI)); + final long lastModified = getCursorLong(recentCursor, RecentsProvider.COL_TIMESTAMP); - final Cursor itemCursor = resolver.query(uri, null, null, null, null); + final Cursor cursor = resolver.query(uri, null, null, null, null); try { - if (!itemCursor.moveToFirst()) { + if (!cursor.moveToFirst()) { throw new IllegalArgumentException("Missing details for " + uri); } - final String mimeType = getCursorString(itemCursor, DocumentColumns.MIME_TYPE); - final String displayName = getCursorString(itemCursor, DocumentColumns.DISPLAY_NAME); - final int flags = getCursorInt(itemCursor, DocumentColumns.FLAGS) + final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); + final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); + final int flags = getCursorInt(cursor, 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, summary, size); } finally { - itemCursor.close(); + cursor.close(); } } @@ -166,4 +167,11 @@ public class Document { return Long.compare(rhs.lastModified, lhs.lastModified); } } + + public static class SizeComparator implements Comparator<Document> { + @Override + public int compare(Document lhs, Document rhs) { + return Long.compare(rhs.size, lhs.size); + } + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java index dade8a3..67dca07 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java @@ -42,7 +42,7 @@ public class DocumentStack extends LinkedList<Document> { } public static DocumentStack deserialize(ContentResolver resolver, String raw) { - Log.d(TAG, "restoreStack: " + raw); + Log.d(TAG, "deserialize: " + raw); final DocumentStack stack = new DocumentStack(); try { diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java index 629dbc4..0880731 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java @@ -27,7 +27,6 @@ import android.provider.DocumentsContract; import android.provider.DocumentsContract.RootColumns; import com.android.documentsui.R; -import com.android.documentsui.RecentsProvider; import java.util.Comparator; @@ -41,6 +40,7 @@ public class Root { public Drawable icon; public String title; public String summary; + public long availableBytes = -1; public boolean isRecents; public static Root buildRecents(Context context) { @@ -52,6 +52,7 @@ public class Root { root.icon = context.getResources().getDrawable(R.drawable.ic_dir); root.title = context.getString(R.string.root_recent); root.summary = null; + root.availableBytes = -1; root.isRecents = true; return root; } @@ -67,6 +68,7 @@ public class Root { info.providerInfo.authority, root.rootId, DocumentsContract.ROOT_DOC_ID); root.icon = info.providerInfo.loadIcon(pm); root.title = info.providerInfo.loadLabel(pm).toString(); + root.availableBytes = cursor.getLong(cursor.getColumnIndex(RootColumns.AVAILABLE_BYTES)); root.summary = null; final int icon = cursor.getInt(cursor.getColumnIndex(RootColumns.ICON)); |