PhotoSetFragment.java revision 1a719804ddd5c6fc9a6914ef5a2b6e914834d1f9
15f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck/*
25f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Copyright (C) 2013 The Android Open Source Project
35f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck *
45f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Licensed under the Apache License, Version 2.0 (the "License");
55f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * you may not use this file except in compliance with the License.
65f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * You may obtain a copy of the License at
75f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck *
85f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck *      http://www.apache.org/licenses/LICENSE-2.0
95f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck *
105f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * Unless required by applicable law or agreed to in writing, software
115f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * distributed under the License is distributed on an "AS IS" BASIS,
125f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * See the License for the specific language governing permissions and
145f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck * limitations under the License.
155f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck */
165f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
175f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckpackage com.android.photos;
185f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
195f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.app.Fragment;
205f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.app.LoaderManager.LoaderCallbacks;
21869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescuimport android.content.Context;
22f6e687bc30887695374580712092aeb917c84253John Reckimport android.content.Intent;
235f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.content.Loader;
245f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.database.Cursor;
25f6e687bc30887695374580712092aeb917c84253John Reckimport android.net.Uri;
265f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.os.Bundle;
27fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescuimport android.util.SparseBooleanArray;
285f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.view.LayoutInflater;
295f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.view.View;
305f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport android.view.ViewGroup;
31f6e687bc30887695374580712092aeb917c84253John Reckimport android.widget.AdapterView;
32f6e687bc30887695374580712092aeb917c84253John Reckimport android.widget.AdapterView.OnItemClickListener;
33d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport android.widget.GridView;
345f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
355f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.gallery3d.R;
36f6e687bc30887695374580712092aeb917c84253John Reckimport com.android.gallery3d.app.Gallery;
37fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescuimport com.android.photos.adapters.PhotoThumbnailAdapter;
385f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reckimport com.android.photos.data.PhotoSetLoader;
39f6e687bc30887695374580712092aeb917c84253John Reckimport com.android.photos.shims.LoaderCompatShim;
40d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reckimport com.android.photos.shims.MediaItemsLoader;
415f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
42fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescuimport java.util.ArrayList;
435f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
44869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescupublic class PhotoSetFragment extends Fragment implements OnItemClickListener,
45869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    LoaderCallbacks<Cursor>, MultiChoiceManager.Delegate, SelectionManager.Client  {
465f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
475f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    private static final int LOADER_PHOTOSET = 1;
485f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
49d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck    private GridView mPhotoSetView;
505f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    private View mEmptyView;
51fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
52f6e687bc30887695374580712092aeb917c84253John Reck    private boolean mInitialLoadComplete = false;
53f6e687bc30887695374580712092aeb917c84253John Reck    private LoaderCompatShim<Cursor> mLoaderCompatShim;
54fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    private PhotoThumbnailAdapter mAdapter;
55869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    private MultiChoiceManager mMultiChoiceManager;
56fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    private SelectionManager mSelectionManager;
575f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
585f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    @Override
59638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck    public void onCreate(Bundle savedInstanceState) {
60638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck        super.onCreate(savedInstanceState);
61869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        Context context = getActivity();
62869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mAdapter = new PhotoThumbnailAdapter(context);
63869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mMultiChoiceManager = new MultiChoiceManager(context, this);
64869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mMultiChoiceManager.setSelectionManager(mSelectionManager);
65869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    }
66869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu
67869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    @Override
68869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public void setSelectionManager(SelectionManager manager) {
69869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mSelectionManager = manager;
70869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        if (mMultiChoiceManager != null) {
71869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu            mMultiChoiceManager.setSelectionManager(manager);
72869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        }
73638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck    }
74638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck
75638d9ec56c26d9f3cff55145ccbd20b35bb964f5John Reck    @Override
765f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    public View onCreateView(LayoutInflater inflater, ViewGroup container,
775f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck            Bundle savedInstanceState) {
785f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        View root = inflater.inflate(R.layout.photo_set, container, false);
79d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        mPhotoSetView = (GridView) root.findViewById(android.R.id.list);
80d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        // TODO: Remove once UI stabilizes
81d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        mPhotoSetView.setColumnWidth(MediaItemsLoader.getThumbnailSize());
82f6e687bc30887695374580712092aeb917c84253John Reck        mPhotoSetView.setOnItemClickListener(this);
835f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        mEmptyView = root.findViewById(android.R.id.empty);
845f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        mEmptyView.setVisibility(View.GONE);
855f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        mPhotoSetView.setAdapter(mAdapter);
86fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu        mPhotoSetView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
87869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mPhotoSetView.setMultiChoiceModeListener(mMultiChoiceManager);
885f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        getLoaderManager().initLoader(LOADER_PHOTOSET, null, this);
895f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        updateEmptyStatus();
905f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        return root;
915f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    }
925f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
935f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    private void updateEmptyStatus() {
945f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        boolean empty = (mAdapter == null || mAdapter.getCount() == 0);
955f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        mPhotoSetView.setVisibility(empty ? View.GONE : View.VISIBLE);
96f6e687bc30887695374580712092aeb917c84253John Reck        mEmptyView.setVisibility(empty && mInitialLoadComplete
97f6e687bc30887695374580712092aeb917c84253John Reck                ? View.VISIBLE : View.GONE);
98f6e687bc30887695374580712092aeb917c84253John Reck    }
99f6e687bc30887695374580712092aeb917c84253John Reck
100f6e687bc30887695374580712092aeb917c84253John Reck    @Override
101f6e687bc30887695374580712092aeb917c84253John Reck    public void onItemClick(AdapterView<?> parent, View view, int position,
102f6e687bc30887695374580712092aeb917c84253John Reck            long id) {
103f6e687bc30887695374580712092aeb917c84253John Reck        if (mLoaderCompatShim == null) {
104f6e687bc30887695374580712092aeb917c84253John Reck            // Not fully initialized yet, discard
105f6e687bc30887695374580712092aeb917c84253John Reck            return;
106f6e687bc30887695374580712092aeb917c84253John Reck        }
107f6e687bc30887695374580712092aeb917c84253John Reck        Cursor item = mAdapter.getItem(position);
108f6e687bc30887695374580712092aeb917c84253John Reck        Uri uri = mLoaderCompatShim.uriForItem(item);
109f6e687bc30887695374580712092aeb917c84253John Reck        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
110f6e687bc30887695374580712092aeb917c84253John Reck        intent.setClass(getActivity(), Gallery.class);
111f6e687bc30887695374580712092aeb917c84253John Reck        startActivity(intent);
1125f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    }
1135f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
1145f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    @Override
1155f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
116d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        // TODO: Switch to PhotoSetLoader
117d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        MediaItemsLoader loader = new MediaItemsLoader(getActivity());
118f6e687bc30887695374580712092aeb917c84253John Reck        mInitialLoadComplete = false;
119f6e687bc30887695374580712092aeb917c84253John Reck        mLoaderCompatShim = loader;
120fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu        mAdapter.setDrawableFactory(mLoaderCompatShim);
121d228222e5efca7df8c7f2fe49e5ec76696cbbc05John Reck        return loader;
1225f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    }
1235f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
1245f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    @Override
1255f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    public void onLoadFinished(Loader<Cursor> loader,
1265f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck            Cursor data) {
1275f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        mAdapter.swapCursor(data);
128f6e687bc30887695374580712092aeb917c84253John Reck        mInitialLoadComplete = true;
1295f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck        updateEmptyStatus();
1305f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    }
1315f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck
132fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
133869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public void onLoaderReset(Loader<Cursor> loader) {
134fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
135fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
1365f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    @Override
137869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public int getItemMediaType(Object item) {
138869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE);
1395f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck    }
14071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck
141869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    @Override
142869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public int getItemSupportedOperations(Object item) {
143869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS);
144fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
14571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck
146fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
147869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public Object getItemAtPosition(int position) {
148869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return mAdapter.getItem(position);
149fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
150fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
151869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1);
152fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
153869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public ArrayList<Uri> getSubItemUrisForItem(Object item) {
154869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mSubItemUriTemp.clear();
155869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item));
156869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return mSubItemUriTemp;
157fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
15871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck
159869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu
160fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
161869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public Object getPathForItemAtPosition(int position) {
162869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return mLoaderCompatShim.getPathForItem(mAdapter.getItem(position));
163fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
164fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
165fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
166869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public void deleteItemWithPath(Object itemPath) {
167869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        mLoaderCompatShim.deleteItemWithPath(itemPath);
168fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
169fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
170fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
171869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public SparseBooleanArray getSelectedItemPositions() {
172869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return mPhotoSetView.getCheckedItemPositions();
173fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    }
174fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu
175fb6132b0b3079153fd1d15acf1dc3c6100aa2e00Bobby Georgescu    @Override
176869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu    public int getSelectedItemCount() {
177869f4a62594c4508aa57a8622b461b6825b74e7cBobby Georgescu        return mPhotoSetView.getCheckedItemCount();
17871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck    }
1791a719804ddd5c6fc9a6914ef5a2b6e914834d1f9Bobby Georgescu
1801a719804ddd5c6fc9a6914ef5a2b6e914834d1f9Bobby Georgescu    @Override
1811a719804ddd5c6fc9a6914ef5a2b6e914834d1f9Bobby Georgescu    public Uri getItemUri(Object item) {
1821a719804ddd5c6fc9a6914ef5a2b6e914834d1f9Bobby Georgescu        return mLoaderCompatShim.uriForItem((Cursor) item);
1831a719804ddd5c6fc9a6914ef5a2b6e914834d1f9Bobby Georgescu    }
1845f30b98d6ac98c6aa863d48f47e9b8e2b77a1820John Reck}
185