diff options
18 files changed, 330 insertions, 61 deletions
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 289531e52a27..acaed73ada9c 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 1d97161fdccb..27f93c0549ae 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 638ac92c129c..8dbd1de3d689 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 85c48b1d9ab7..49038bcd4461 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 ad8f51cb1a07..244214ba5bb5 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 bb2717372370..37c588129ec7 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 d57f88ab247b..575336ca46a8 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 2ff5d0309b63..84f89b4afb10 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 000000000000..5589ff18583d --- /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 d986a512e9da..5a6060ac4467 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 6784d709dbbb..fae567374062 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 2651e4c358a3..1e018e73f04d 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 c4e9c15aa686..427ad42faccc 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 304f6e3a7ed8..69010dd64ef1 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 000000000000..ceeaaaebb7da --- /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 3b82ba8c4b17..f2744658da5f 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 dade8a357b97..67dca07673b0 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 629dbc4d8b72..08807312e613 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)); |