OSDN Git Service

Start of photos
authorJohn Reck <jreck@google.com>
Fri, 15 Feb 2013 22:32:08 +0000 (14:32 -0800)
committerJohn Reck <jreck@google.com>
Fri, 22 Feb 2013 23:09:35 +0000 (15:09 -0800)
Change-Id: Id53dd96d8873e0fe6c2685e07cd7bdc0cde7ea75

src/com/android/gallery3d/data/DataManager.java
src/com/android/photos/AlbumSetFragment.java [new file with mode: 0644]
src/com/android/photos/GalleryActivity.java [new file with mode: 0644]
src/com/android/photos/PhotoFragment.java [new file with mode: 0644]
src/com/android/photos/PhotoSetFragment.java [new file with mode: 0644]
src/com/android/photos/data/MediaSetLoader.java [new file with mode: 0644]
src/com/android/photos/data/PhotoSetLoader.java [new file with mode: 0644]

index 8fcf400..38865e9 100644 (file)
 
 package com.android.gallery3d.data;
 
+import android.content.Context;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
 
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.app.StitchingChangeListener;
-import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
 import com.android.gallery3d.data.MediaSet.ItemConsumer;
@@ -65,6 +65,11 @@ public class DataManager implements StitchingChangeListener {
     // to prevent concurrency issue.
     public static final Object LOCK = new Object();
 
+    public static DataManager from(Context context) {
+        GalleryApp app = (GalleryApp) context.getApplicationContext();
+        return app.getDataManager();
+    }
+
     private static final String TAG = "DataManager";
 
     // This is the path for the media set seen by the user at top level.
diff --git a/src/com/android/photos/AlbumSetFragment.java b/src/com/android/photos/AlbumSetFragment.java
new file mode 100644 (file)
index 0000000..2d348c2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.photos;
+
+import android.app.Fragment;
+
+
+public class AlbumSetFragment extends Fragment {
+
+}
diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java
new file mode 100644 (file)
index 0000000..46b5140
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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.photos;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.camera.CameraActivity;
+import com.android.gallery3d.R;
+
+public class GalleryActivity extends Activity {
+
+    private final String FTAG_PHOTOSET = "PhotoSet";
+    private final String FTAG_ALBUMSET = "AlbumSet";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setupActionBar();
+    }
+
+    private void setupActionBar() {
+        ActionBar ab = getActionBar();
+        ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+        ab.setDisplayShowHomeEnabled(false);
+        ab.setDisplayShowTitleEnabled(false);
+        Tab tab = ab.newTab();
+        tab.setText(R.string.tab_photos);
+        tab.setTabListener(new TabListener<PhotoSetFragment>(this,
+                FTAG_PHOTOSET, PhotoSetFragment.class));
+        ab.addTab(tab, true);
+        tab = ab.newTab();
+        tab.setText(R.string.tab_albums);
+        tab.setTabListener(new TabListener<AlbumSetFragment>(this,
+                FTAG_ALBUMSET, AlbumSetFragment.class));
+        ab.addTab(tab);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.gallery, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+        case R.id.menu_camera:
+            Intent intent = new Intent(this, CameraActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(intent);
+            return true;
+        default:
+            return super.onOptionsItemSelected(item);
+        }
+    }
+
+    private static class TabListener<T extends Fragment> implements ActionBar.TabListener {
+        private Fragment mFragment;
+        private final Activity mActivity;
+        private final String mTag;
+        private final Class<T> mClass;
+
+        /** Constructor used each time a new tab is created.
+          * @param activity  The host Activity, used to instantiate the fragment
+          * @param tag  The identifier tag for the fragment
+          * @param clz  The fragment's Class, used to instantiate the fragment
+          */
+        public TabListener(Activity activity, String tag, Class<T> clz) {
+            mActivity = activity;
+            mTag = tag;
+            mClass = clz;
+        }
+
+        /* The following are each of the ActionBar.TabListener callbacks */
+
+        @Override
+        public void onTabSelected(Tab tab, FragmentTransaction ft) {
+            // Check if the fragment is already initialized
+            if (mFragment == null) {
+                // If not, instantiate and add it to the activity
+                mFragment = Fragment.instantiate(mActivity, mClass.getName());
+                ft.add(android.R.id.content, mFragment, mTag);
+            } else {
+                // If it exists, simply attach it in order to show it
+                ft.attach(mFragment);
+            }
+        }
+
+        @Override
+        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+            if (mFragment != null) {
+                // Detach the fragment, because another one is being attached
+                ft.detach(mFragment);
+            }
+        }
+
+        @Override
+        public void onTabReselected(Tab tab, FragmentTransaction ft) {
+            // User selected the already selected tab. Usually do nothing.
+        }
+    }
+}
diff --git a/src/com/android/photos/PhotoFragment.java b/src/com/android/photos/PhotoFragment.java
new file mode 100644 (file)
index 0000000..3be6313
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.photos;
+
+import android.app.Fragment;
+
+
+public class PhotoFragment extends Fragment {
+
+}
diff --git a/src/com/android/photos/PhotoSetFragment.java b/src/com/android/photos/PhotoSetFragment.java
new file mode 100644 (file)
index 0000000..e9bfce5
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.photos;
+
+import android.app.Fragment;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.MediaStore.Files.FileColumns;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+
+import com.android.gallery3d.R;
+import com.android.photos.data.PhotoSetLoader;
+
+
+public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor> {
+
+    private static final int LOADER_PHOTOSET = 1;
+
+    private ListView mPhotoSetView;
+    private View mEmptyView;
+    private CursorAdapter mAdapter;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        View root = inflater.inflate(R.layout.photo_set, container, false);
+        mPhotoSetView = (ListView) root.findViewById(android.R.id.list);
+        mEmptyView = root.findViewById(android.R.id.empty);
+        mEmptyView.setVisibility(View.GONE);
+        mAdapter = new SimpleCursorAdapter(getActivity(),
+                android.R.layout.simple_list_item_1, null,
+                new String[] { FileColumns.DATA },
+                new int[] { android.R.id.text1 }, 0);
+        mPhotoSetView.setAdapter(mAdapter);
+        getLoaderManager().initLoader(LOADER_PHOTOSET, null, this);
+        updateEmptyStatus();
+        return root;
+    }
+
+    private void updateEmptyStatus() {
+        boolean empty = (mAdapter == null || mAdapter.getCount() == 0);
+        mPhotoSetView.setVisibility(empty ? View.GONE : View.VISIBLE);
+        mEmptyView.setVisibility(empty ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+        return new PhotoSetLoader(getActivity());
+    }
+
+    @Override
+    public void onLoadFinished(Loader<Cursor> loader,
+            Cursor data) {
+        mAdapter.swapCursor(data);
+        updateEmptyStatus();
+    }
+
+    @Override
+    public void onLoaderReset(Loader<Cursor> loader) {
+    }
+}
diff --git a/src/com/android/photos/data/MediaSetLoader.java b/src/com/android/photos/data/MediaSetLoader.java
new file mode 100644 (file)
index 0000000..4afb7d9
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.photos.data;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+
+import com.android.gallery3d.data.ContentListener;
+import com.android.gallery3d.data.DataManager;
+import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.MediaSet.SyncListener;
+import com.android.gallery3d.util.Future;
+
+/**
+ * Proof of concept, don't use
+ */
+public class MediaSetLoader extends AsyncTaskLoader<MediaSet> {
+
+    private static final SyncListener sNullListener = new SyncListener() {
+        @Override
+        public void onSyncDone(MediaSet mediaSet, int resultCode) {
+        }
+    };
+
+    private MediaSet mMediaSet;
+    private Future<Integer> mSyncTask = null;
+    private ContentListener mObserver = new ContentListener() {
+        @Override
+        public void onContentDirty() {
+            onContentChanged();
+        }
+    };
+
+    public MediaSetLoader(Context context, String path) {
+        super(context);
+        mMediaSet = DataManager.from(getContext()).getMediaSet(path);
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        mMediaSet.addContentListener(mObserver);
+        mSyncTask = mMediaSet.requestSync(sNullListener);
+        forceLoad();
+    }
+
+    @Override
+    protected boolean onCancelLoad() {
+        if (mSyncTask != null) {
+            mSyncTask.cancel();
+            mSyncTask = null;
+        }
+        return super.onCancelLoad();
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+        mMediaSet.removeContentListener(mObserver);
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        onStopLoading();
+    }
+
+    @Override
+    public MediaSet loadInBackground() {
+        mMediaSet.loadIfDirty();
+        return mMediaSet;
+    }
+
+}
diff --git a/src/com/android/photos/data/PhotoSetLoader.java b/src/com/android/photos/data/PhotoSetLoader.java
new file mode 100644 (file)
index 0000000..8c511a5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.photos.data;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Files.FileColumns;
+
+public class PhotoSetLoader extends CursorLoader {
+
+    private static final Uri CONTENT_URI = Files.getContentUri("external");
+    private static final String[] PROJECTION = new String[] {
+        FileColumns._ID,
+        FileColumns.DATA,
+        FileColumns.WIDTH,
+        FileColumns.HEIGHT,
+        FileColumns.DATE_ADDED,
+        FileColumns.MEDIA_TYPE,
+    };
+    private static final String SORT_ORDER = FileColumns.DATE_ADDED + " DESC";
+    private static final String SELECTION =
+            FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_IMAGE
+            + " OR "
+            + FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_VIDEO;
+
+    public static final int INDEX_ID = 0;
+    public static final int INDEX_DATA = 1;
+    public static final int INDEX_WIDTH = 2;
+    public static final int INDEX_HEIGHT = 3;
+    public static final int INDEX_DATE_ADDED = 4;
+    public static final int INDEX_MEDIA_TYPE = 5;
+
+    private static final Uri GLOBAL_CONTENT_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/external/");
+    private final ContentObserver mGlobalObserver = new ForceLoadContentObserver();
+
+    public PhotoSetLoader(Context context) {
+        super(context, CONTENT_URI, PROJECTION, SELECTION, null, SORT_ORDER);
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        getContext().getContentResolver().registerContentObserver(GLOBAL_CONTENT_URI,
+                true, mGlobalObserver);
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        getContext().getContentResolver().unregisterContentObserver(mGlobalObserver);
+    }
+}