DocumentsActivity.java revision 0c2d31bfa113c2848620ac05c916802410b71da1
19e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey/*
29e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project
39e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
49e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
59e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * you may not use this file except in compliance with the License.
69e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * You may obtain a copy of the License at
79e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
89e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
99e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey *
109e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
119e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * See the License for the specific language governing permissions and
149e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * limitations under the License.
159e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey */
169e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypackage com.android.documentsui;
189e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.ActionBar;
2054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.ActionBar.OnNavigationListener;
219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.Activity;
229fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkeyimport android.app.Fragment;
239e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentManager;
24be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ClipData;
25be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.content.ContentResolver;
2620d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkeyimport android.content.ContentValues;
279e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Intent;
2854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.database.Cursor;
29bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.graphics.drawable.ColorDrawable;
309e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri;
319e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle;
3254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.provider.DocumentsContract.DocumentColumns;
33bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.app.ActionBarDrawerToggle;
34bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.view.GravityCompat;
35bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout;
36bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.support.v4.widget.DrawerLayout.DrawerListener;
379e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.util.Log;
389e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater;
3954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu;
4054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem;
419e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View;
429e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup;
4354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.BaseAdapter;
44bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView;
45b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.widget.SearchView.OnCloseListener;
46bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkeyimport android.widget.SearchView.OnQueryTextListener;
4754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.TextView;
487e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkeyimport android.widget.Toast;
499e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
50ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport com.android.documentsui.model.Document;
51b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport com.android.documentsui.model.DocumentStack;
52ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport com.android.documentsui.model.Root;
5320d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey
540c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkeyimport java.io.FileNotFoundException;
55be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.Arrays;
56be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.List;
57be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypublic class DocumentsActivity extends Activity {
59ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final String TAG = "Documents";
609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
61b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public static final int ACTION_OPEN = 1;
62b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public static final int ACTION_CREATE = 2;
6354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
641482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    private int mAction;
65be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
66bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private SearchView mSearchView;
67bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
6866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private View mRootsContainer;
69bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerLayout mDrawerLayout;
70bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private ActionBarDrawerToggle mDrawerToggle;
71bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
721482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    private final DisplayState mDisplayState = new DisplayState();
731482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
74b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    /** Current user navigation stack; empty implies recents. */
75b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private DocumentStack mStack;
76b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    /** Currently active search, overriding any stack. */
77b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private String mCurrentSearch;
7854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
799e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
809e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public void onCreate(Bundle icicle) {
819e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        super.onCreate(icicle);
829e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
83be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        final Intent intent = getIntent();
84be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        final String action = intent.getAction();
8554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
861482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            mAction = ACTION_OPEN;
87ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            mDisplayState.allowMultiple = intent.getBooleanExtra(
88ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    Intent.EXTRA_ALLOW_MULTIPLE, false);
8954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
901482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            mAction = ACTION_CREATE;
911482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            mDisplayState.allowMultiple = false;
92be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
93be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
94be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
95ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            mDisplayState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
96be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else {
97ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            mDisplayState.acceptMimes = new String[] { intent.getType() };
9854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
9954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
100ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        if (MimePredicate.mimeMatches("image/*", mDisplayState.acceptMimes)) {
1011482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            mDisplayState.mode = DisplayState.MODE_GRID;
1021482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        } else {
1031482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            mDisplayState.mode = DisplayState.MODE_LIST;
1041482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        }
1051482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
1069e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        setResult(Activity.RESULT_CANCELED);
10754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        setContentView(R.layout.activity);
10854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1091482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        if (mAction == ACTION_CREATE) {
11054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String mimeType = getIntent().getType();
11154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
11254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            SaveFragment.show(getFragmentManager(), mimeType, title);
11354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
114bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
11566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        RootsFragment.show(getFragmentManager());
11666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
11766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mRootsContainer = findViewById(R.id.container_roots);
11866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
119bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
120bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
121bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
122bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
123bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
124bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mDrawerLayout.setDrawerListener(mDrawerListener);
125bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
126bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
12766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        mDrawerLayout.openDrawer(mRootsContainer);
128dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
129dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        // Restore last stack for calling package
130dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        // TODO: move into async loader
131dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final String packageName = getCallingPackage();
132dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Cursor cursor = getContentResolver()
133dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                .query(RecentsProvider.buildResume(packageName), null, null, null, null);
134dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        try {
135dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            if (cursor.moveToFirst()) {
136b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                final String raw = cursor.getString(
137dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                        cursor.getColumnIndex(RecentsProvider.COL_PATH));
138b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                mStack = DocumentStack.deserialize(getContentResolver(), raw);
139dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            }
1400c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey        } catch (FileNotFoundException e) {
1410c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey            Log.w(TAG, "Failed to resume", e);
142dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        } finally {
143dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            cursor.close();
144dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
145dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
1469fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        onCurrentDirectoryChanged();
147bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    }
148bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
149bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private DrawerListener mDrawerListener = new DrawerListener() {
150bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
151bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerSlide(View drawerView, float slideOffset) {
152bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
153bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
154bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
155bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
156bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerOpened(View drawerView) {
157bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerOpened(drawerView);
158bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            updateActionBar();
159bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
160bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
161bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
162bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerClosed(View drawerView) {
163bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerClosed(drawerView);
164bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            updateActionBar();
165bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
166bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
167bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
168bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public void onDrawerStateChanged(int newState) {
169bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            mDrawerToggle.onDrawerStateChanged(newState);
170bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
171bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    };
172bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
173bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    @Override
174bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    protected void onPostCreate(Bundle savedInstanceState) {
175bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        super.onPostCreate(savedInstanceState);
176bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mDrawerToggle.syncState();
1779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
1789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
17954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public void updateActionBar() {
18054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final ActionBar actionBar = getActionBar();
1819e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
182bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        actionBar.setDisplayShowHomeEnabled(true);
183bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        actionBar.setDisplayHomeAsUpEnabled(true);
1849e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
18566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        if (mDrawerLayout.isDrawerOpen(mRootsContainer)) {
18654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
187bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            actionBar.setIcon(new ColorDrawable());
18854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1891482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            if (mAction == ACTION_OPEN) {
19054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                actionBar.setTitle(R.string.title_open);
1911482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            } else if (mAction == ACTION_CREATE) {
19254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                actionBar.setTitle(R.string.title_save);
19354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            }
194bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
195bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else {
196dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            final Root root = getCurrentRoot();
197dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            actionBar.setIcon(root != null ? root.icon : null);
198ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
199b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            if (root.isRecents) {
200ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
201ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setTitle(root.title);
202ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            } else {
203ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
204ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setTitle(null);
205ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setListNavigationCallbacks(mSortAdapter, mSortListener);
206ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                actionBar.setSelectedNavigationItem(mDisplayState.sortOrder);
207ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            }
208bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
209dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            if (mStack.size() > 1) {
210bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                mDrawerToggle.setDrawerIndicatorEnabled(false);
211bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            } else {
212bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                mDrawerToggle.setDrawerIndicatorEnabled(true);
213bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
2149e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
21554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
2169e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
21754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
21854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onCreateOptionsMenu(Menu menu) {
21954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onCreateOptionsMenu(menu);
22054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        getMenuInflater().inflate(R.menu.activity, menu);
221bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
222bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem searchMenu = menu.findItem(R.id.menu_search);
223bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView = (SearchView) searchMenu.getActionView();
224bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
225bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
226bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextSubmit(String query) {
227b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                mCurrentSearch = query;
2289fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                onCurrentDirectoryChanged();
229bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                mSearchView.setIconified(true);
230bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return true;
231bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
232bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
233bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            @Override
234bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            public boolean onQueryTextChange(String newText) {
235bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                return false;
236bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
237bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        });
238bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
239b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        mSearchView.setOnCloseListener(new OnCloseListener() {
240b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            @Override
241b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            public boolean onClose() {
242b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                mCurrentSearch = null;
2439fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                onCurrentDirectoryChanged();
244b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                return false;
245b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
246b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        });
247b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
24854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
24954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
25054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
25154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
25254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onPrepareOptionsMenu(Menu menu) {
25354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        super.onPrepareOptionsMenu(menu);
25454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
2559fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final FragmentManager fm = getFragmentManager();
256dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Document cwd = getCurrentDirectory();
257dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
25854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
259bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        final MenuItem search = menu.findItem(R.id.menu_search);
2609fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final MenuItem grid =  menu.findItem(R.id.menu_grid);
2619fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final MenuItem list = menu.findItem(R.id.menu_list);
262dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
2639fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID);
2649fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST);
2659fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
2669fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        final boolean searchVisible;
267dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (mAction == ACTION_CREATE) {
2689fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(cwd != null && cwd.isCreateSupported());
2699fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            searchVisible = false;
2709fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
2719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // No display options in recent directories
2729fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (cwd == null) {
2739fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                grid.setVisible(false);
2749fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                list.setVisible(false);
2759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
2769fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
277dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
2789fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        } else {
2799fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            createDir.setVisible(false);
2809fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            searchVisible = cwd != null && cwd.isSearchSupported();
281dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
282bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
2839fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // TODO: close any search in-progress when hiding
2849fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        search.setVisible(searchVisible);
285b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
28654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return true;
2879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
2889e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
28954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    @Override
29054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public boolean onOptionsItemSelected(MenuItem item) {
291bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        if (mDrawerToggle.onOptionsItemSelected(item)) {
292bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
293bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
294bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
29554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final int id = item.getItemId();
29654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        if (id == android.R.id.home) {
297dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            onBackPressed();
298bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
29954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        } else if (id == R.id.menu_create_dir) {
30020d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey            CreateDirectoryFragment.show(getFragmentManager());
301bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return true;
302bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        } else if (id == R.id.menu_search) {
303bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return false;
304b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_grid) {
305b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            mDisplayState.mode = DisplayState.MODE_GRID;
306b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            updateDisplayState();
307b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            invalidateOptionsMenu();
308b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
309b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else if (id == R.id.menu_list) {
310b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            mDisplayState.mode = DisplayState.MODE_LIST;
311b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            updateDisplayState();
312b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            invalidateOptionsMenu();
313b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return true;
3149fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        } else if (id == R.id.menu_settings) {
3159fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            startActivity(new Intent(this, SettingsActivity.class));
3169fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            return true;
317b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
318b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return super.onOptionsItemSelected(item);
31954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
32054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
32154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
322dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    @Override
323dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    public void onBackPressed() {
324dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final int size = mStack.size();
325dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (size > 1) {
326dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            mStack.pop();
3279fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            onCurrentDirectoryChanged();
32866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        } else if (size == 1 && !mDrawerLayout.isDrawerOpen(mRootsContainer)) {
329dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // TODO: open root drawer once we can capture back key
330dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
331dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        } else {
332dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            super.onBackPressed();
33354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
334dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
33554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
336bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    // TODO: support additional sort orders
337bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private BaseAdapter mSortAdapter = new BaseAdapter() {
33854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
33954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public int getCount() {
3409fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            return mDisplayState.showSize ? 3 : 2;
34154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
3429e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
34354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
34454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public Object getItem(int position) {
345bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            switch (position) {
346bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                case 0:
347bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                    return getText(R.string.sort_name);
348bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                case 1:
349bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                    return getText(R.string.sort_date);
3509fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                case 2:
3519fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                    return getText(R.string.sort_size);
352bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                default:
353bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                    return null;
354bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
35554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
3569e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
35754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
35854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public long getItemId(int position) {
359bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return position;
3609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
3619e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
3629e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
36354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
36454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            if (convertView == null) {
36554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
366bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                        .inflate(R.layout.item_title, parent, false);
367bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
368bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
369bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
370bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
371bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
372dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            final Document cwd = getCurrentDirectory();
373dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            if (cwd != null) {
374dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                title.setText(cwd.displayName);
375bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            } else {
376b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // No directory means recents
377b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                title.setText(R.string.root_recent);
378bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            }
379bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
380bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            summary.setText((String) getItem(position));
381bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
382bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            return convertView;
383bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        }
384bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
385bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        @Override
386bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey        public View getDropDownView(int position, View convertView, ViewGroup parent) {
387bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            if (convertView == null) {
388bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                convertView = LayoutInflater.from(parent.getContext())
38954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey                        .inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
3909e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
3919e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
39254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
393bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey            text1.setText((String) getItem(position));
3949e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
39554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            return convertView;
3969e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
39754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
3989e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
399bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey    private OnNavigationListener mSortListener = new OnNavigationListener() {
4009e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
40154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public boolean onNavigationItemSelected(int itemPosition, long itemId) {
402ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            mDisplayState.sortOrder = itemPosition;
403b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            updateDisplayState();
40454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            return true;
40554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
40654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
40754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
408dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    public Root getCurrentRoot() {
409b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        final Document cwd = getCurrentDirectory();
410b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (cwd != null) {
411b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return RootsCache.findRoot(this, cwd);
412b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
413b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            return RootsCache.getRecentsRoot(this);
414b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
415dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
416dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
417dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    public Document getCurrentDirectory() {
418dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        return mStack.peek();
419dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
420dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
4211482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    public DisplayState getDisplayState() {
4221482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        return mDisplayState;
4231482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
4241482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
4259fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    private void onCurrentDirectoryChanged() {
426dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final FragmentManager fm = getFragmentManager();
427dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Document cwd = getCurrentDirectory();
4289fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
429b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (cwd == null) {
430b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            // No directory means recents
431b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            if (mAction == ACTION_CREATE) {
432b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                RecentsCreateFragment.show(fm);
433b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
434b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                DirectoryFragment.showRecentsOpen(fm);
435b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
436b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
437b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            if (mCurrentSearch != null) {
438b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Ongoing search
439b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                DirectoryFragment.showSearch(fm, cwd.uri, mCurrentSearch);
440b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
441b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                // Normal boring directory
442b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                DirectoryFragment.showNormal(fm, cwd.uri);
443b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
44454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
445b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
4469fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // Forget any replacement target
4479fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        if (mAction == ACTION_CREATE) {
4489fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final SaveFragment save = SaveFragment.get(fm);
4499fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (save != null) {
4509fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                save.setReplaceTarget(null);
4519fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
4529fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        }
4539fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
454dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        updateActionBar();
45554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        invalidateOptionsMenu();
456dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        dumpStack();
45754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
45854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
459b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private void updateDisplayState() {
460b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        // TODO: handle multiple directory stacks on tablets
461b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        DirectoryFragment.get(getFragmentManager()).updateDisplayState();
462b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
463b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
464b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public void onStackPicked(DocumentStack stack) {
465b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        mStack = stack;
4669fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        onCurrentDirectoryChanged();
467b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
468b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
46966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public void onRootPicked(Root root, boolean closeDrawer) {
470ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        // Clear entire backstack and start in new root
471ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        mStack.clear();
472b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
473b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (!root.isRecents) {
4740c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey            try {
4750c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey                onDocumentPicked(Document.fromRoot(getContentResolver(), root));
4760c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey            } catch (FileNotFoundException e) {
4770c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey            }
478b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        } else {
4799fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            onCurrentDirectoryChanged();
480b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        }
48166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
48266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        if (closeDrawer) {
48366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey            mDrawerLayout.closeDrawers();
48466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        }
485ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
486ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
48754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    public void onDocumentPicked(Document doc) {
48854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final FragmentManager fm = getFragmentManager();
489b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        if (doc.isDirectory()) {
490dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            mStack.push(doc);
4919fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            onCurrentDirectoryChanged();
4921482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        } else if (mAction == ACTION_OPEN) {
49354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            // Explicit file picked, return
49454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            onFinished(doc.uri);
4951482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        } else if (mAction == ACTION_CREATE) {
4969fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            // Replace selected file
4979fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            SaveFragment.get(fm).setReplaceTarget(doc);
49854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
49954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
50054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
501be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    public void onDocumentsPicked(List<Document> docs) {
502be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        final int size = docs.size();
503be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        final Uri[] uris = new Uri[size];
504be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        for (int i = 0; i < size; i++) {
505be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            uris[i] = docs.get(i).uri;
506be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
507be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        onFinished(uris);
508be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    }
509be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
5109fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public void onSaveRequested(Document replaceTarget) {
5119fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        onFinished(replaceTarget.uri);
5129fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
51392d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey
5149fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public void onSaveRequested(String mimeType, String displayName) {
51520d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey        final ContentValues values = new ContentValues();
51620d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey        values.put(DocumentColumns.MIME_TYPE, mimeType);
51720d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey        values.put(DocumentColumns.DISPLAY_NAME, displayName);
51820d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey
519dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Document cwd = getCurrentDirectory();
520dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Uri childUri = getContentResolver().insert(cwd.uri, values);
521dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (childUri != null) {
522dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            onFinished(childUri);
5237e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkey        } else {
5247e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkey            Toast.makeText(this, R.string.save_error, Toast.LENGTH_SHORT).show();
5257e258b31e70464bb6d80b8b42f0cef8e4417bd6aJeff Sharkey        }
52654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
52754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
528be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    private void onFinished(Uri... uris) {
529be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
53054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
531dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentResolver resolver = getContentResolver();
532dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final ContentValues values = new ContentValues();
533dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
534b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        final String rawStack = DocumentStack.serialize(mStack);
535dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        if (mAction == ACTION_CREATE) {
536dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // Remember stack for last create
537dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            values.clear();
538b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            values.put(RecentsProvider.COL_PATH, rawStack);
539dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            resolver.insert(RecentsProvider.buildRecentCreate(), values);
540dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
541dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        } else if (mAction == ACTION_OPEN) {
542dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            // Remember opened items
543dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            for (Uri uri : uris) {
544dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                values.clear();
545dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                values.put(RecentsProvider.COL_URI, uri.toString());
546dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                resolver.insert(RecentsProvider.buildRecentOpen(), values);
547dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            }
548dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
549dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
550dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        // Remember location for next app launch
551dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final String packageName = getCallingPackage();
552dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        values.clear();
553b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        values.put(RecentsProvider.COL_PATH, rawStack);
554dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        resolver.insert(RecentsProvider.buildResume(packageName), values);
555dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
55654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final Intent intent = new Intent();
557be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        if (uris.length == 1) {
558be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setData(uris[0]);
559be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else if (uris.length > 1) {
560ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final ClipData clipData = new ClipData(
561ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    null, mDisplayState.acceptMimes, new ClipData.Item(uris[0]));
562be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            for (int i = 1; i < uris.length; i++) {
563be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                clipData.addItem(new ClipData.Item(uris[i]));
564be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            }
565be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            intent.setClipData(clipData);
566be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
56754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
56820d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey        // TODO: omit WRITE and PERSIST for GET_CONTENT
56920d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
57020d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
57120d96d8aff2193d548977e23ce5158657cac94e0Jeff Sharkey                | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
57254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
57354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        setResult(Activity.RESULT_OK, intent);
57454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        finish();
57554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
57654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
5771482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    public static class DisplayState {
578ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public int mode = MODE_LIST;
579ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public String[] acceptMimes;
580ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public int sortOrder = SORT_ORDER_NAME;
581ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public boolean allowMultiple = false;
582b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        public boolean showSize = false;
5831482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
5841482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        public static final int MODE_LIST = 0;
5851482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        public static final int MODE_GRID = 1;
5861482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
587ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public static final int SORT_ORDER_NAME = 0;
588ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public static final int SORT_ORDER_DATE = 1;
5899fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        public static final int SORT_ORDER_SIZE = 2;
5901482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    }
5911482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
592dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    private void dumpStack() {
593dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        Log.d(TAG, "Current stack:");
594dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        for (Document doc : mStack) {
595dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey            Log.d(TAG, "--> " + doc);
596dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        }
597dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    }
5989fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
5999fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    public static DocumentsActivity get(Fragment fragment) {
6009fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        return (DocumentsActivity) fragment.getActivity();
6019fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    }
6029e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey}
603