Merge "Settings, replace files, sorting by size, tweaks."
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 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.provider.DocumentsContract;
import android.text.format.DateUtils;
import android.text.format.Formatter;
-import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
@@ -62,11 +61,14 @@
*/
public class DirectoryFragment extends Fragment {
+ private View mEmptyView;
private ListView mListView;
private GridView mGridView;
private AbsListView mCurrentView;
+ private Predicate<Document> mFilter;
+
public static final int TYPE_NORMAL = 1;
public static final int TYPE_SEARCH = 2;
public static final int TYPE_RECENT_OPEN = 3;
@@ -121,6 +123,8 @@
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
+ mEmptyView = view.findViewById(android.R.id.empty);
+
mListView = (ListView) view.findViewById(R.id.list);
mListView.setOnItemClickListener(mItemListener);
mListView.setMultiChoiceModeListener(mMultiListener);
@@ -138,6 +142,7 @@
@Override
public Loader<List<Document>> onCreateLoader(int id, Bundle args) {
final DisplayState state = getDisplayState(DirectoryFragment.this);
+ mFilter = new MimePredicate(state.acceptMimes);
final Uri contentsUri;
if (mType == TYPE_NORMAL) {
@@ -148,18 +153,18 @@
contentsUri = uri;
}
- final Predicate<Document> filter = new MimePredicate(state.acceptMimes);
-
final Comparator<Document> sortOrder;
if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
sortOrder = new Document.DateComparator();
} else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) {
sortOrder = new Document.NameComparator();
+ } else if (state.sortOrder == DisplayState.SORT_ORDER_SIZE) {
+ sortOrder = new Document.SizeComparator();
} else {
throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
}
- return new DirectoryLoader(context, contentsUri, mType, filter, sortOrder);
+ return new DirectoryLoader(context, contentsUri, mType, null, sortOrder);
}
@Override
@@ -181,6 +186,10 @@
@Override
public void onStart() {
super.onStart();
+
+ final Context context = getActivity();
+ getDisplayState(this).showSize = SettingsActivity.getDisplayFileSize(context);
+
getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
}
@@ -193,7 +202,7 @@
public void updateDisplayState() {
final DisplayState state = getDisplayState(this);
- // TODO: avoid kicking loader when sort didn't change
+ // TODO: avoid kicking loader when nothing changed
getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
mListView.smoothScrollToPosition(0);
mGridView.smoothScrollToPosition(0);
@@ -302,6 +311,13 @@
public void swapDocuments(List<Document> documents) {
mDocuments = documents;
+
+ if (documents != null && documents.isEmpty()) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ }
+
notifyDataSetChanged();
}
@@ -325,6 +341,7 @@
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+ final View summaryGrid = convertView.findViewById(R.id.summary_grid);
final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
final TextView date = (TextView) convertView.findViewById(R.id.date);
@@ -356,6 +373,11 @@
summary.setVisibility(View.VISIBLE);
}
+ if (summaryGrid != null) {
+ summaryGrid.setVisibility(
+ (summary.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE);
+ }
+
// TODO: omit year from format
date.setText(DateUtils.formatSameDayTime(
doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT,
@@ -389,5 +411,16 @@
public long getItemId(int position) {
return getItem(position).uri.hashCode();
}
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ final Document doc = getItem(position);
+ return mFilter.apply(doc);
+ }
}
}
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 @@
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 @@
cursor.close();
}
- updateDirectoryFragment();
+ onCurrentDirectoryChanged();
}
private DrawerListener mDrawerListener = new DrawerListener() {
@@ -221,7 +224,7 @@
@Override
public boolean onQueryTextSubmit(String query) {
mCurrentSearch = query;
- updateDirectoryFragment();
+ onCurrentDirectoryChanged();
mSearchView.setIconified(true);
return true;
}
@@ -236,7 +239,7 @@
@Override
public boolean onClose() {
mCurrentSearch = null;
- updateDirectoryFragment();
+ onCurrentDirectoryChanged();
return false;
}
});
@@ -248,23 +251,36 @@
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 @@
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 @@
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 @@
private BaseAdapter mSortAdapter = new BaseAdapter() {
@Override
public int getCount() {
- return 2;
+ return mDisplayState.showSize ? 3 : 2;
}
@Override
@@ -327,6 +346,8 @@
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 @@
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 @@
}
}
+ // 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 void onStackPicked(DocumentStack stack) {
mStack = stack;
- updateDirectoryFragment();
+ onCurrentDirectoryChanged();
}
public void onRootPicked(Root root, boolean closeDrawer) {
@@ -442,7 +472,7 @@
if (!root.isRecents) {
onDocumentPicked(Document.fromRoot(getContentResolver(), root));
} else {
- updateDirectoryFragment();
+ onCurrentDirectoryChanged();
}
if (closeDrawer) {
@@ -454,13 +484,13 @@
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 @@
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 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 @@
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 @@
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.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 @@
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 @@
@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 @@
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 @@
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.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.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 @@
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 @@
return view;
}
- private View.OnClickListener mSaveListener = new View.OnClickListener() {
+ private TextWatcher mDisplayNameWatcher = new TextWatcher() {
@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);
+ 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
}
};
- public void setDisplayName(String displayName) {
- getArguments().putString(EXTRA_DISPLAY_NAME, displayName);
- mDisplayName.setText(displayName);
+ private View.OnClickListener mSaveListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ 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);
+ }
+ }
+ };
+
+ /**
+ * 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.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
+import android.util.Log;
import com.android.documentsui.RecentsProvider;
@@ -69,25 +70,25 @@
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 @@
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 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.RootColumns;
import com.android.documentsui.R;
-import com.android.documentsui.RecentsProvider;
import java.util.Comparator;
@@ -41,6 +40,7 @@
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 @@
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 @@
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));