summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/camera/CameraActivity.java29
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java105
-rw-r--r--src/com/android/gallery3d/filtershow/PanelController.java19
-rw-r--r--src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java4
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java5
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java64
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java19
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java26
-rw-r--r--src/com/android/gallery3d/filtershow/presets/ImagePreset.java7
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ImageCurves.java1
-rw-r--r--src/com/android/photos/data/PhotoDatabase.java111
-rw-r--r--src/com/android/photos/data/PhotoProvider.java514
12 files changed, 742 insertions, 162 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index a207b2b71..b5ff0114c 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -19,8 +19,8 @@ package com.android.camera;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.content.Context;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
@@ -30,13 +30,14 @@ import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.provider.Settings;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.camera.ui.CameraSwitcher;
@@ -62,6 +63,7 @@ public class CameraActivity extends ActivityBase
private int mCurrentModuleIndex;
private MotionEvent mDown;
private boolean mAutoRotateScreen;
+ private int mHeightOrWidth = -1;
private MyOrientationEventListener mOrientationListener;
// The degrees of the device rotated clockwise from its natural orientation.
@@ -299,6 +301,15 @@ public class CameraActivity extends ActivityBase
super.onConfigurationChanged(config);
ViewGroup appRoot = (ViewGroup) findViewById(R.id.content);
+ boolean landscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE);
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) appRoot.getLayoutParams();
+ if (landscape) {
+ lp.rightMargin = getResources().getDimensionPixelSize(R.dimen.margin_systemui_offset);
+ } else {
+ lp.rightMargin = 0;
+ }
+ appRoot.setLayoutParams(lp);
+
// remove old switcher, shutter and shutter icon
View cameraControlsView = findViewById(R.id.camera_shutter_switcher);
appRoot.removeView(cameraControlsView);
@@ -362,9 +373,23 @@ public class CameraActivity extends ActivityBase
hideUI();
}
super.onFullScreenChanged(full);
+ if (ApiHelper.HAS_ROTATION_ANIMATION) {
+ setRotationAnimation(full);
+ }
mCurrentModule.onFullScreenChanged(full);
}
+ private void setRotationAnimation(boolean fullscreen) {
+ int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+ if (fullscreen) {
+ rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
+ }
+ Window win = getWindow();
+ WindowManager.LayoutParams winParams = win.getAttributes();
+ winParams.rotationAnimation = rotationAnimation;
+ win.setAttributes(winParams);
+ }
+
@Override
protected void onStop() {
super.onStop();
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index fd30ac080..516a19250 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -60,9 +60,7 @@ import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
import com.android.gallery3d.filtershow.filters.*;
import com.android.gallery3d.filtershow.imageshow.ImageCrop;
-import com.android.gallery3d.filtershow.imageshow.ImageDraw;
import com.android.gallery3d.filtershow.imageshow.ImageFlip;
-import com.android.gallery3d.filtershow.imageshow.ImageRedEye;
import com.android.gallery3d.filtershow.imageshow.ImageRotate;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
@@ -98,18 +96,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private final PanelController mPanelController = new PanelController();
private ImageLoader mImageLoader = null;
private ImageShow mImageShow = null;
- private ImageDraw mImageDraw = null;
private ImageStraighten mImageStraighten = null;
private ImageCrop mImageCrop = null;
private ImageRotate mImageRotate = null;
private ImageFlip mImageFlip = null;
private ImageTinyPlanet mImageTinyPlanet = null;
- private View mListFx = null;
- private View mListBorders = null;
- private View mListGeometry = null;
- private View mListColors = null;
- private View mListFilterButtons = null;
private View mSaveButton = null;
private ImageButton mFxButton = null;
@@ -117,10 +109,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private ImageButton mGeometryButton = null;
private ImageButton mColorsButton = null;
- private LinearLayout listColors = null;
- private LinearLayout listFilters = null;
- private LinearLayout listBorders = null;
-
private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
private static final int SELECT_PICTURE = 1;
@@ -132,8 +120,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private boolean mShowingImageStatePanel = false;
private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
- private final Vector<View> mListViews = new Vector<View>();
- private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>();
private ShareActionProvider mShareActionProvider;
private File mSharedOutputFile = null;
@@ -141,14 +127,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private boolean mSharingImage = false;
private WeakReference<ProgressDialog> mSavingProgressDialog;
- private static final int SEEK_BAR_MAX = 600;
private LoadBitmapTask mLoadBitmapTask;
private FilterIconButton mNullFxFilter;
private FilterIconButton mNullBorderFilter;
private int mIconSeedSize = 140;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -192,17 +176,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageLoader = new ImageLoader(this, getApplicationContext());
- listFilters = (LinearLayout) findViewById(R.id.listFilters);
- listBorders = (LinearLayout) findViewById(R.id.listBorders);
- listColors = (LinearLayout) findViewById(R.id.listColorsFx);
-
mImageShow = (ImageShow) findViewById(R.id.imageShow);
mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet);
- mImageDraw = (ImageDraw) findViewById(R.id.imageDraw);
mImageCrop.setAspectTextSize((int) getPixelsFromDip(18));
ImageCrop.setTouchTolerance((int) getPixelsFromDip(25));
@@ -226,34 +205,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mEditorPlaceHolder.hide();
- mListFx = findViewById(R.id.fxList);
- mListBorders = findViewById(R.id.bordersList);
- mListGeometry = findViewById(R.id.geometryList);
- mListFilterButtons = findViewById(R.id.filterButtonsList);
- mListColors = findViewById(R.id.colorsFxList);
- mListViews.add(mListFx);
- mListViews.add(mListBorders);
- mListViews.add(mListGeometry);
- mListViews.add(mListFilterButtons);
- mListViews.add(mListColors);
-
mFxButton = (ImageButton) findViewById(R.id.fxButton);
mBorderButton = (ImageButton) findViewById(R.id.borderButton);
mGeometryButton = (ImageButton) findViewById(R.id.geometryButton);
mColorsButton = (ImageButton) findViewById(R.id.colorsButton);
- mBottomPanelButtons.add(mFxButton);
- mBottomPanelButtons.add(mBorderButton);
- mBottomPanelButtons.add(mGeometryButton);
- mBottomPanelButtons.add(mColorsButton);
-
mImageShow.setImageLoader(mImageLoader);
mImageStraighten.setImageLoader(mImageLoader);
mImageCrop.setImageLoader(mImageLoader);
mImageRotate.setImageLoader(mImageLoader);
mImageFlip.setImageLoader(mImageLoader);
mImageTinyPlanet.setImageLoader(mImageLoader);
- mImageDraw.setImageLoader(mImageLoader);
mPanelController.setActivity(this);
mPanelController.setEditorPlaceHolder(mEditorPlaceHolder);
@@ -264,18 +226,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.addImageView(findViewById(R.id.imageRotate));
mPanelController.addImageView(findViewById(R.id.imageFlip));
mPanelController.addImageView(findViewById(R.id.imageTinyPlanet));
- mPanelController.addImageView(findViewById(R.id.imageDraw));
- mPanelController.addPanel(mFxButton, mListFx, 0);
- mPanelController.addPanel(mBorderButton, mListBorders, 1);
+ mPanelController.addPanel(mFxButton, findViewById(R.id.fxList), 0);
+ mPanelController.addPanel(mBorderButton, findViewById(R.id.bordersList), 1);
- mPanelController.addPanel(mGeometryButton, mListGeometry, 2);
+ mPanelController.addPanel(mGeometryButton, findViewById(R.id.geometryList), 2);
mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton));
mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
- mPanelController.addPanel(mColorsButton, mListColors, 3);
+ mPanelController.addPanel(mColorsButton, findViewById(R.id.colorsFxList), 3);
Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
@@ -283,7 +244,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
filtersManager.addEffects(filtersRepresentations);
for (FilterRepresentation representation : filtersRepresentations) {
- setupFilterRepresentationButton(representation, listColors, mColorsButton);
+ setupFilterRepresentationButton(representation,
+ (LinearLayout) findViewById(R.id.listColorsFx), mColorsButton);
}
mPanelController.addView(findViewById(R.id.applyEffect));
@@ -297,8 +259,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
imageStateList.setAdapter(mMasterImage.getState());
mImageLoader.setAdapter(mMasterImage.getHistory());
- fillListImages(listFilters);
- LoadBordersTask loadBorders = new LoadBordersTask(listBorders);
+ fillListImages((LinearLayout) findViewById(R.id.listFilters));
+ LoadBordersTask loadBorders = new LoadBordersTask((LinearLayout) findViewById(R.id.listBorders));
loadBorders.execute();
mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
@@ -483,22 +445,24 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
h = h * f;
bmap = Bitmap.createScaledBitmap(bmap, (int) w, (int) h, true);
+ LinearLayout listColors = (LinearLayout) findViewById(R.id.listColorsFx);
int num_colors_buttons = listColors.getChildCount();
for (int i = 0; i < num_colors_buttons; i++) {
FilterIconButton b = (FilterIconButton) listColors.getChildAt(i);
-
b.setIcon(bmap);
}
+
+ LinearLayout listFilters = (LinearLayout) findViewById(R.id.listFilters);
int num_filters_buttons = listFilters.getChildCount();
for (int i = 0; i < num_filters_buttons; i++) {
FilterIconButton b = (FilterIconButton) listFilters.getChildAt(i);
-
b.setIcon(bmap);
}
+
+ LinearLayout listBorders = (LinearLayout) findViewById(R.id.listBorders);
int num_borders_buttons = listBorders.getChildCount();
for (int i = 0; i < num_borders_buttons; i++) {
FilterIconButton b = (FilterIconButton) listBorders.getChildAt(i);
-
b.setIcon(bmap);
}
@@ -521,9 +485,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
if (mLoadBitmapTask != null) {
mLoadBitmapTask.cancel(false);
}
+ // TODO: Using singletons is a bad design choice for many of these
+ // due static reference leaks and in general. Please refactor.
MasterImage.reset();
FilteringPipeline.reset();
ImageFilter.resetStatics();
+ FiltersManager.reset();
super.onDestroy();
}
@@ -799,12 +766,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
// Some utility functions
// TODO: finish the cleanup.
- public void showOriginalViews(boolean value) {
- for (ImageShow views : mImageViews) {
- views.showOriginal(value);
- }
- }
-
public void invalidateViews() {
for (ImageShow views : mImageViews) {
views.invalidate();
@@ -812,12 +773,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
}
- public void hideListViews() {
- for (View view : mListViews) {
- view.setVisibility(View.GONE);
- }
- }
-
public void hideImageViews() {
for (View view : mImageViews) {
view.setVisibility(View.GONE);
@@ -825,34 +780,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mEditorPlaceHolder.hide();
}
- public void unselectBottomPanelButtons() {
- for (ImageButton button : mBottomPanelButtons) {
- button.setSelected(false);
- }
- }
-
- public void unselectPanelButtons(Vector<ImageButton> buttons) {
- for (ImageButton button : buttons) {
- button.setSelected(false);
- }
- }
-
- public void disableFilterButtons() {
- for (ImageButton b : mBottomPanelButtons) {
- b.setEnabled(false);
- b.setClickable(false);
- b.setAlpha(0.4f);
- }
- }
-
- public void enableFilterButtons() {
- for (ImageButton b : mBottomPanelButtons) {
- b.setEnabled(true);
- b.setClickable(true);
- b.setAlpha(1.0f);
- }
- }
-
// //////////////////////////////////////////////////////////////////////////////
// imageState panel...
diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java
index 5bda246da..3c3de894e 100644
--- a/src/com/android/gallery3d/filtershow/PanelController.java
+++ b/src/com/android/gallery3d/filtershow/PanelController.java
@@ -46,7 +46,6 @@ public class PanelController implements OnClickListener {
private static int HORIZONTAL_MOVE = 1;
private static final int ANIM_DURATION = 200;
private static final String LOGTAG = "PanelController";
- private boolean mDisableFilterButtons = false;
private boolean mFixedAspect = false;
public static boolean useAnimations() {
@@ -312,10 +311,6 @@ public class PanelController implements OnClickListener {
}
}
- if (mDisableFilterButtons) {
- mActivity.enableFilterButtons();
- mDisableFilterButtons = false;
- }
}
public boolean onBackPressed() {
@@ -330,12 +325,6 @@ public class PanelController implements OnClickListener {
if (mCurrentEditor != null) {
mCurrentEditor.reflectCurrentFilter();
}
-
- if (mDisableFilterButtons) {
- mActivity.enableFilterButtons();
- mActivity.resetHistory();
- mDisableFilterButtons = false;
- }
return false;
}
@@ -447,6 +436,10 @@ public class PanelController implements OnClickListener {
return MasterImage.getImage().getPreset();
}
+ public void setEffectName(String ename) {
+ mUtilityPanel.setEffectName(ename);
+ }
+
public void useFilterRepresentation(FilterRepresentation filterRepresentation) {
if (filterRepresentation == null) {
return;
@@ -537,10 +530,6 @@ public class PanelController implements OnClickListener {
mCurrentImage = showImageView(R.id.imageTinyPlanet);
String ename = mCurrentImage.getContext().getString(R.string.tinyplanet);
mUtilityPanel.setEffectName(ename);
- if (!mDisableFilterButtons) {
- mActivity.disableFilterButtons();
- mDisableFilterButtons = true;
- }
break;
}
case R.id.straightenButton: {
diff --git a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
index 0af406316..9c6415bc9 100644
--- a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
+++ b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
@@ -22,7 +22,6 @@ import android.os.Process;
import android.support.v8.renderscript.*;
import android.util.Log;
-import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilterRS;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
@@ -250,7 +249,8 @@ public class FilteringPipeline implements Handler.Callback {
setPresetParameters(preset);
if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
- bitmap = MasterImage.getImage().getImageLoader().getScaleOneImageForPreset(null, preset, request.getBounds(), request.getDestination(), false);
+ bitmap = MasterImage.getImage().getImageLoader().getScaleOneImageForPreset(null, preset,
+ request.getBounds(), request.getDestination(), false);
if (bitmap == null) {
return;
}
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index b502a2ffe..b5ed9eee0 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -315,6 +315,7 @@ public class ImageLoader {
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
+ o2.inMutable = true;
Utils.closeSilently(is);
is = mContext.getContentResolver().openInputStream(uri);
@@ -376,9 +377,9 @@ public class ImageLoader {
mLoadingLock.lock();
Bitmap bmp = mZoomCache.getImage(imagePreset, bounds);
if (force || bmp == null) {
- BitmapFactory.Options options = null;
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inMutable = true;
if (destination != null) {
- options = new BitmapFactory.Options();
if (bounds.width() > destination.width()) {
int sampleSize = 1;
int w = bounds.width();
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index 377bd2b6f..4dbf91a33 100644
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -13,49 +13,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.gallery3d.filtershow.filters;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-
import java.util.HashMap;
+import java.util.Map;
import java.util.Vector;
-public class BaseFiltersManager {
-
- private static final String LOGTAG = "BaseFiltersManager";
- private static HashMap<Class, ImageFilter> mFilters = new HashMap<Class, ImageFilter>();
-
- protected BaseFiltersManager() {
- Vector<ImageFilter> filters = new Vector<ImageFilter>();
- addFilters(filters);
- for (ImageFilter filter : filters) {
- mFilters.put(filter.getClass(), filter);
- }
- }
+public abstract class BaseFiltersManager {
+ protected HashMap<Class, ImageFilter> mFilters = null;
- protected void addFilters(Vector<ImageFilter> filters) {
- filters.add(new ImageFilterTinyPlanet());
- filters.add(new ImageFilterRedEye());
- filters.add(new ImageFilterWBalance());
- filters.add(new ImageFilterExposure());
- filters.add(new ImageFilterVignette());
- filters.add(new ImageFilterContrast());
- filters.add(new ImageFilterShadows());
- filters.add(new ImageFilterHighlights());
- filters.add(new ImageFilterVibrance());
- filters.add(new ImageFilterSharpen());
- filters.add(new ImageFilterCurves());
- filters.add(new ImageFilterDraw());
- filters.add(new ImageFilterHue());
- filters.add(new ImageFilterSaturated());
- filters.add(new ImageFilterBwFilter());
- filters.add(new ImageFilterNegative());
- filters.add(new ImageFilterEdge());
- filters.add(new ImageFilterKMeans());
- filters.add(new ImageFilterFx());
- filters.add(new ImageFilterBorder());
- filters.add(new ImageFilterParametricBorder());
+ protected void addFilters(Map<Class, ImageFilter> filters) {
+ filters.put(ImageFilterTinyPlanet.class, new ImageFilterTinyPlanet());
+ filters.put(ImageFilterRedEye.class, new ImageFilterRedEye());
+ filters.put(ImageFilterWBalance.class, new ImageFilterWBalance());
+ filters.put(ImageFilterExposure.class, new ImageFilterExposure());
+ filters.put(ImageFilterVignette.class, new ImageFilterVignette());
+ filters.put(ImageFilterContrast.class, new ImageFilterContrast());
+ filters.put(ImageFilterShadows.class, new ImageFilterShadows());
+ filters.put(ImageFilterHighlights.class, new ImageFilterHighlights());
+ filters.put(ImageFilterVibrance.class, new ImageFilterVibrance());
+ filters.put(ImageFilterSharpen.class, new ImageFilterSharpen());
+ filters.put(ImageFilterCurves.class, new ImageFilterCurves());
+ filters.put(ImageFilterDraw.class, new ImageFilterDraw());
+ filters.put(ImageFilterHue.class, new ImageFilterHue());
+ filters.put(ImageFilterSaturated.class, new ImageFilterSaturated());
+ filters.put(ImageFilterBwFilter.class, new ImageFilterBwFilter());
+ filters.put(ImageFilterNegative.class, new ImageFilterNegative());
+ filters.put(ImageFilterEdge.class, new ImageFilterEdge());
+ filters.put(ImageFilterKMeans.class, new ImageFilterKMeans());
+ filters.put(ImageFilterFx.class, new ImageFilterFx());
+ filters.put(ImageFilterBorder.class, new ImageFilterBorder());
+ filters.put(ImageFilterParametricBorder.class, new ImageFilterParametricBorder());
}
public ImageFilter getFilter(Class c) {
@@ -79,7 +67,7 @@ public class BaseFiltersManager {
}
public void addLooks(Vector<FilterRepresentation> representations) {
- // subclass can add representations
+ // Override
}
public void addEffects(Vector<FilterRepresentation> representations) {
diff --git a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
index b4ca8e1f1..a2a2e8568 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
@@ -158,7 +158,24 @@ public class EclipseControl {
}
}
- void paintPoint(Canvas canvas, float x, float y) {
+ public void paintGrayPoint(Canvas canvas, float x, float y) {
+ if (x == Float.NaN) {
+ return;
+ }
+
+ Paint paint = new Paint();
+
+ paint.setStyle(Paint.Style.FILL);
+ paint.setColor(Color.BLUE);
+ int[] colors3 = new int[] {
+ Color.GRAY, Color.LTGRAY, 0x66000000, 0 };
+ RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] {
+ 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP);
+ paint.setShader(g);
+ canvas.drawCircle(x, y, mCenterDotSize, paint);
+ }
+
+ public void paintPoint(Canvas canvas, float x, float y) {
if (x == Float.NaN) {
return;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 39e0cc82b..a52d383f2 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -289,11 +289,6 @@ public class ImageShow extends View implements OnGestureListener,
}
}
- public void defaultDrawImage(Canvas canvas) {
- drawImage(canvas, getFilteredImage());
- drawPartialImage(canvas, getGeometryOnlyImage());
- }
-
@Override
public void onDraw(Canvas canvas) {
MasterImage.getImage().setImageShowSize(getWidth(), getHeight());
@@ -306,7 +301,7 @@ public class ImageShow extends View implements OnGestureListener,
canvas.scale(scaleFactor, scaleFactor, cx, cy);
canvas.translate(translation.x, translation.y);
drawBackground(canvas);
- defaultDrawImage(canvas);
+ drawImage(canvas, getFilteredImage());
canvas.restore();
if (showTitle() && getImagePreset() != null) {
@@ -326,6 +321,13 @@ public class ImageShow extends View implements OnGestureListener,
Rect dest = new Rect(0, 0, getWidth(), getHeight());
canvas.drawBitmap(partialPreview, src, dest, mPaint);
}
+
+ canvas.save();
+ canvas.scale(scaleFactor, scaleFactor, cx, cy);
+ canvas.translate(translation.x, translation.y);
+ drawPartialImage(canvas, getGeometryOnlyImage());
+ canvas.restore();
+
drawToast(canvas);
}
@@ -374,7 +376,7 @@ public class ImageShow extends View implements OnGestureListener,
canvas.save();
if (image != null) {
if (mShowOriginalDirection == 0) {
- if ((mTouch.y - mTouchDown.y) > (mTouch.x - mTouchDown.x)) {
+ if (Math.abs(mTouch.y - mTouchDown.y) > Math.abs(mTouch.x - mTouchDown.x)) {
mShowOriginalDirection = UNVEIL_VERTICAL;
} else {
mShowOriginalDirection = UNVEIL_HORIZONTAL;
@@ -397,16 +399,18 @@ public class ImageShow extends View implements OnGestureListener,
drawImage(canvas, image);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
+ paint.setStrokeWidth(3);
if (mShowOriginalDirection == UNVEIL_VERTICAL) {
- canvas.drawLine(mImageBounds.left, mTouch.y - 1,
- mImageBounds.right, mTouch.y - 1, paint);
+ canvas.drawLine(mImageBounds.left, mTouch.y,
+ mImageBounds.right, mTouch.y, paint);
} else {
- canvas.drawLine(mTouch.x - 1, mImageBounds.top,
- mTouch.x - 1, mImageBounds.bottom, paint);
+ canvas.drawLine(mTouch.x, mImageBounds.top,
+ mTouch.x, mImageBounds.bottom, paint);
}
Rect bounds = new Rect();
+ paint.setAntiAlias(true);
paint.setTextSize(mOriginalTextSize);
paint.getTextBounds(mOriginalText, 0, mOriginalText.length(), bounds);
paint.setColor(Color.BLACK);
diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
index ae5a03414..1400fd4de 100644
--- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
@@ -22,7 +22,6 @@ import android.util.Log;
import com.android.gallery3d.filtershow.ImageStateAdapter;
import com.android.gallery3d.filtershow.cache.ImageLoader;
-import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -428,6 +427,12 @@ public class ImagePreset {
if (mGeoData.hasModifications()) {
return false;
}
+ if (mBorder != null && !mBorder.supportsPartialRendering()) {
+ return false;
+ }
+ if (ImageLoader.getZoomOrientation() != 0) {
+ return false;
+ }
for (int i = 0; i < mFilters.size(); i++) {
FilterRepresentation representation = null;
synchronized (mFilters) {
diff --git a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
index e54c83eff..3e52f5ee5 100644
--- a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
+++ b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
@@ -35,7 +35,6 @@ import android.widget.PopupMenu;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.editors.EditorCurves;
-import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
diff --git a/src/com/android/photos/data/PhotoDatabase.java b/src/com/android/photos/data/PhotoDatabase.java
new file mode 100644
index 000000000..64a857fcc
--- /dev/null
+++ b/src/com/android/photos/data/PhotoDatabase.java
@@ -0,0 +1,111 @@
+/*
+ * 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.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import com.android.photos.data.PhotoProvider.Albums;
+import com.android.photos.data.PhotoProvider.Metadata;
+import com.android.photos.data.PhotoProvider.Photos;
+
+/**
+ * Used in PhotoProvider to create and access the database containing
+ * information about photo and video information stored on the server.
+ */
+public class PhotoDatabase extends SQLiteOpenHelper {
+ @SuppressWarnings("unused")
+ private static final String TAG = PhotoDatabase.class.getSimpleName();
+ static final String DB_NAME = "photo.db";
+ static final int DB_VERSION = 1;
+
+ private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
+
+ private static final String[][] CREATE_PHOTO = {
+ { Photos._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ { Photos.SERVER_ID, "INTEGER UNIQUE" },
+ { Photos.WIDTH, "INTEGER NOT NULL" },
+ { Photos.HEIGHT, "INTEGER NOT NULL" },
+ { Photos.DATE_TAKEN, "INTEGER NOT NULL" },
+ // Photos.ALBUM_ID is a foreign key to Albums._ID
+ { Photos.ALBUM_ID, "INTEGER" },
+ { Photos.MIME_TYPE, "TEXT NOT NULL" },
+ };
+
+ private static final String[][] CREATE_ALBUM = {
+ { Albums._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ // Albums.PARENT_ID is a foriegn key to Albums._ID
+ { Albums.PARENT_ID, "INTEGER" },
+ { Albums.NAME, "Text NOT NULL" },
+ { Albums.VISIBILITY, "INTEGER NOT NULL" },
+ { Albums.SERVER_ID, "INTEGER UNIQUE" },
+ createUniqueConstraint(Albums.PARENT_ID, Albums.NAME),
+ };
+
+ private static final String[][] CREATE_METADATA = {
+ { Metadata._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+ // Metadata.PHOTO_ID is a foreign key to Photos._ID
+ { Metadata.PHOTO_ID, "INTEGER NOT NULL" },
+ { Metadata.KEY, "TEXT NOT NULL" },
+ { Metadata.VALUE, "TEXT NOT NULL" },
+ createUniqueConstraint(Metadata.PHOTO_ID, Metadata.KEY),
+ };
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createTable(db, Albums.TABLE, CREATE_ALBUM);
+ createTable(db, Photos.TABLE, CREATE_PHOTO);
+ createTable(db, Metadata.TABLE, CREATE_METADATA);
+ }
+
+ public PhotoDatabase(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+
+ protected static void createTable(SQLiteDatabase db, String table, String[][] columns) {
+ StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
+ create.append(table).append('(');
+ boolean first = true;
+ for (String[] column : columns) {
+ if (!first) {
+ create.append(',');
+ }
+ first = false;
+ for (String val: column) {
+ create.append(val).append(' ');
+ }
+ }
+ create.append(')');
+ db.beginTransaction();
+ try {
+ db.execSQL(create.toString());
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ protected static String[] createUniqueConstraint(String column1, String column2) {
+ return new String[] {
+ "UNIQUE(", column1, ",", column2, ")"
+ };
+ }
+}
diff --git a/src/com/android/photos/data/PhotoProvider.java b/src/com/android/photos/data/PhotoProvider.java
new file mode 100644
index 000000000..eefa37349
--- /dev/null
+++ b/src/com/android/photos/data/PhotoProvider.java
@@ -0,0 +1,514 @@
+/*
+ * 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.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.provider.BaseColumns;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A provider that gives access to photo and video information for media stored
+ * on the server. Only media that is or will be put on the server will be
+ * accessed by this provider. Use Photos.CONTENT_URI to query all photos and
+ * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI
+ * to query metadata about a photo or video, based on the ID of the media. Use
+ * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or
+ * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview,
+ * or original-sized image respectfully. <br/>
+ * To add or update metadata, use the update function rather than insert. All
+ * values for the metadata must be in the ContentValues, even if they are also
+ * in the selection. The selection and selectionArgs are not used when updating
+ * metadata. If the metadata values are null, the row will be deleted.
+ */
+public class PhotoProvider extends ContentProvider {
+ @SuppressWarnings("unused")
+ private static final String TAG = PhotoProvider.class.getSimpleName();
+ static final String AUTHORITY = "com.android.gallery3d.photoprovider";
+ static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY)
+ .build();
+
+ /**
+ * Contains columns that can be accessed via PHOTOS_CONTENT_URI.
+ */
+ public static interface Photos extends BaseColumns {
+ /**
+ * Internal database table used for basic photo information.
+ */
+ public static final String TABLE = "photo";
+ /**
+ * Content URI for basic photo and video information.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Identifier used on the server. Long value.
+ */
+ public static final String SERVER_ID = "server_id";
+ /**
+ * Column name for the width of the original image. Integer value.
+ */
+ public static final String WIDTH = "width";
+ /**
+ * Column name for the height of the original image. Integer value.
+ */
+ public static final String HEIGHT = "height";
+ /**
+ * Column name for the date that the original image was taken. Long
+ * value indicating the milliseconds since epoch in the GMT time zone.
+ */
+ public static final String DATE_TAKEN = "date_taken";
+ /**
+ * Column name indicating the long value of the album id that this image
+ * resides in. Will be NULL if it it has not been uploaded to the
+ * server.
+ */
+ public static final String ALBUM_ID = "album_id";
+ /**
+ * The column name for the mime-type String.
+ */
+ public static final String MIME_TYPE = "mime_type";
+ }
+
+ /**
+ * Contains columns and Uri for accessing album information.
+ */
+ public static interface Albums extends BaseColumns {
+ /**
+ * Internal database table used album information.
+ */
+ public static final String TABLE = "album";
+ /**
+ * Content URI for album information.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Parent directory or null if this is in the root.
+ */
+ public static final String PARENT_ID = "parent";
+ /**
+ * Column name for the name of the album. String value.
+ */
+ public static final String NAME = "name";
+ /**
+ * Column name for the visibility level of the album. Can be any of the
+ * VISIBILITY_* values.
+ */
+ public static final String VISIBILITY = "visibility";
+ /**
+ * Column name for the server identifier for this album. NULL if the
+ * server doesn't have this album yet.
+ */
+ public static final String SERVER_ID = "server_id";
+
+ // Privacy values for Albums.VISIBILITY
+ public static final int VISIBILITY_PRIVATE = 1;
+ public static final int VISIBILITY_SHARED = 2;
+ public static final int VISIBILITY_PUBLIC = 3;
+ }
+
+ /**
+ * Contains columns and Uri for accessing photo and video metadata
+ */
+ public static interface Metadata extends BaseColumns {
+ /**
+ * Internal database table used metadata information.
+ */
+ public static final String TABLE = "metadata";
+ /**
+ * Content URI for photo and video metadata.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+ /**
+ * Foreign key to photo_id. Long value.
+ */
+ public static final String PHOTO_ID = "photo_id";
+ /**
+ * Metadata key. String value
+ */
+ public static final String KEY = "key";
+ /**
+ * Metadata value. Type is based on key.
+ */
+ public static final String VALUE = "value";
+ }
+
+ /**
+ * Contains columns and Uri for maintaining the image cache.
+ */
+ public static interface ImageCache extends BaseColumns {
+ /**
+ * Internal database table used for the image cache
+ */
+ public static final String TABLE = "image_cache";
+
+ /**
+ * The image_type query parameter required for accessing a specific
+ * image
+ */
+ public static final String IMAGE_TYPE_QUERY_PARAMETER = "image_type";
+
+ // ImageCache.IMAGE_TYPE values
+ public static final int IMAGE_TYPE_THUMBNAIL = 1;
+ public static final int IMAGE_TYPE_PREVIEW = 2;
+ public static final int IMAGE_TYPE_ORIGINAL = 3;
+
+ /**
+ * Content URI for retrieving image paths. The
+ * IMAGE_TYPE_QUERY_PARAMETER must be used in queries.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE);
+
+ /**
+ * Foreign key to the photos._id. Long value.
+ */
+ public static final String PHOTO_ID = "photos_id";
+ /**
+ * One of IMAGE_TYPE_* values.
+ */
+ public static final String IMAGE_TYPE = "image_type";
+ /**
+ * The String path to the image.
+ */
+ public static final String PATH = "path";
+ };
+
+ // SQL used within this class.
+ protected static final String WHERE_ID = BaseColumns._ID + " = ?";
+ protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND "
+ + Metadata.KEY + " = ?";
+
+ protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM "
+ + Albums.TABLE;
+ protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM "
+ + Photos.TABLE;
+ protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE;
+ protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE;
+ protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE;
+ protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE;
+ protected static final String WHERE = " WHERE ";
+ protected static final String IN = " IN ";
+ protected static final String NESTED_SELECT_START = "(";
+ protected static final String NESTED_SELECT_END = ")";
+
+ /**
+ * For selecting the mime-type for an image.
+ */
+ private static final String[] PROJECTION_MIME_TYPE = {
+ Photos.MIME_TYPE,
+ };
+
+ private SQLiteOpenHelper mOpenHelper;
+ protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ protected static final int MATCH_PHOTO = 1;
+ protected static final int MATCH_PHOTO_ID = 2;
+ protected static final int MATCH_ALBUM = 3;
+ protected static final int MATCH_ALBUM_ID = 4;
+ protected static final int MATCH_METADATA = 5;
+ protected static final int MATCH_METADATA_ID = 6;
+ protected static final int MATCH_IMAGE = 7;
+
+ static {
+ sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO);
+ // match against Photos._ID
+ sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID);
+ sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM);
+ // match against Albums._ID
+ sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID);
+ sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA);
+ // match against metadata/<Metadata._ID>
+ sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID);
+ // match against image_cache/<ImageCache.PHOTO_ID>
+ sUriMatcher.addURI(AUTHORITY, ImageCache.TABLE + "/#", MATCH_IMAGE);
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ int match = matchUri(uri);
+ if (match == MATCH_IMAGE) {
+ throw new IllegalArgumentException("Cannot delete from image cache");
+ }
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ List<Uri> changeUris = new ArrayList<Uri>();
+ int deleted = 0;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ deleted = deleteCascade(db, match, selection, selectionArgs, changeUris, uri);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ for (Uri changeUri : changeUris) {
+ notifyChanges(changeUri);
+ }
+ return deleted;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null);
+ String mimeType = null;
+ if (cursor.moveToNext()) {
+ mimeType = cursor.getString(0);
+ }
+ cursor.close();
+ return mimeType;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Cannot insert into this ContentProvider
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = createDatabaseHelper();
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return query(uri, projection, selection, selectionArgs, sortOrder, null);
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder, CancellationSignal cancellationSignal) {
+ int match = matchUri(uri);
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ String table = getTableFromMatch(match, uri);
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ return db.query(false, table, projection, selection, selectionArgs, null, null, sortOrder,
+ null, cancellationSignal);
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ int match = matchUri(uri);
+ int rowsUpdated = 0;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ if (match == MATCH_METADATA) {
+ rowsUpdated = modifyMetadata(db, values);
+ } else {
+ selection = addIdToSelection(match, selection);
+ selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs);
+ String table = getTableFromMatch(match, uri);
+ rowsUpdated = db.update(table, values, selection, selectionArgs);
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ notifyChanges(uri);
+ return rowsUpdated;
+ }
+
+ protected static String addIdToSelection(int match, String selection) {
+ String where;
+ switch (match) {
+ case MATCH_PHOTO_ID:
+ case MATCH_ALBUM_ID:
+ case MATCH_METADATA_ID:
+ where = WHERE_ID;
+ break;
+ default:
+ return selection;
+ }
+ return DatabaseUtils.concatenateWhere(selection, where);
+ }
+
+ protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) {
+ String[] whereArgs;
+ switch (match) {
+ case MATCH_PHOTO_ID:
+ case MATCH_ALBUM_ID:
+ case MATCH_METADATA_ID:
+ whereArgs = new String[] {
+ uri.getPathSegments().get(1),
+ };
+ break;
+ default:
+ return selectionArgs;
+ }
+ return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs);
+ }
+
+ protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) {
+ List<String> segments = uri.getPathSegments();
+ String[] additionalArgs = {
+ segments.get(1),
+ segments.get(2),
+ };
+
+ return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs);
+ }
+
+ protected static String getTableFromMatch(int match, Uri uri) {
+ String table;
+ switch (match) {
+ case MATCH_PHOTO:
+ case MATCH_PHOTO_ID:
+ table = Photos.TABLE;
+ break;
+ case MATCH_ALBUM:
+ case MATCH_ALBUM_ID:
+ table = Albums.TABLE;
+ break;
+ case MATCH_METADATA:
+ case MATCH_METADATA_ID:
+ table = Metadata.TABLE;
+ break;
+ default:
+ throw unknownUri(uri);
+ }
+ return table;
+ }
+
+ protected final SQLiteOpenHelper getDatabaseHelper() {
+ return mOpenHelper;
+ }
+
+ protected SQLiteOpenHelper createDatabaseHelper() {
+ return new PhotoDatabase(getContext());
+ }
+
+ private int modifyMetadata(SQLiteDatabase db, ContentValues values) {
+ String[] selectionArgs = {
+ values.getAsString(Metadata.PHOTO_ID),
+ values.getAsString(Metadata.KEY),
+ };
+ int rowCount;
+ if (values.get(Metadata.VALUE) == null) {
+ rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs);
+ } else {
+ rowCount = (int) DatabaseUtils.queryNumEntries(db, Metadata.TABLE, WHERE_METADATA_ID,
+ selectionArgs);
+ if (rowCount > 0) {
+ db.update(Metadata.TABLE, values, WHERE_METADATA_ID, selectionArgs);
+ } else {
+ db.insert(Metadata.TABLE, null, values);
+ rowCount = 1;
+ }
+ }
+ return rowCount;
+ }
+
+ private int matchUri(Uri uri) {
+ int match = sUriMatcher.match(uri);
+ if (match == UriMatcher.NO_MATCH) {
+ throw unknownUri(uri);
+ }
+ return match;
+ }
+
+ protected void notifyChanges(Uri uri) {
+ ContentResolver resolver = getContext().getContentResolver();
+ resolver.notifyChange(uri, null, false);
+ }
+
+ protected static IllegalArgumentException unknownUri(Uri uri) {
+ return new IllegalArgumentException("Unknown Uri format: " + uri);
+ }
+
+ protected static String nestSql(String base, String columnMatch, String nested) {
+ StringBuilder sql = new StringBuilder(base);
+ sql.append(WHERE);
+ sql.append(columnMatch);
+ sql.append(IN);
+ sql.append(NESTED_SELECT_START);
+ sql.append(nested);
+ sql.append(NESTED_SELECT_END);
+ return sql.toString();
+ }
+
+ protected static String addWhere(String base, String where) {
+ if (where == null || where.isEmpty()) {
+ return base;
+ }
+ return base + WHERE + where;
+ }
+
+ protected static int deleteCascade(SQLiteDatabase db, int match, String selection,
+ String[] selectionArgs, List<Uri> changeUris, Uri uri) {
+ switch (match) {
+ case MATCH_PHOTO:
+ case MATCH_PHOTO_ID: {
+ String selectPhotoIdsSql = addWhere(SELECT_PHOTO_ID, selection);
+ deleteCascadeMetadata(db, selectPhotoIdsSql, selectionArgs, changeUris);
+ break;
+ }
+ case MATCH_ALBUM:
+ case MATCH_ALBUM_ID: {
+ String selectAlbumIdSql = addWhere(SELECT_ALBUM_ID, selection);
+ deleteCascadePhotos(db, selectAlbumIdSql, selectionArgs, changeUris);
+ break;
+ }
+ }
+ String table = getTableFromMatch(match, uri);
+ changeUris.add(uri);
+ return db.delete(table, selection, selectionArgs);
+ }
+
+ protected static void execSql(SQLiteDatabase db, String sql, String[] args) {
+ if (args == null) {
+ db.execSQL(sql);
+ } else {
+ db.execSQL(sql, args);
+ }
+ }
+
+ private static void deleteCascadePhotos(SQLiteDatabase db, String albumSelect,
+ String[] selectArgs, List<Uri> changeUris) {
+ String selectPhotoIdSql = nestSql(SELECT_PHOTO_ID, Photos.ALBUM_ID, albumSelect);
+ deleteCascadeMetadata(db, selectPhotoIdSql, selectArgs, changeUris);
+ String deletePhotoSql = nestSql(DELETE_PHOTOS, Photos.ALBUM_ID, albumSelect);
+ SQLiteStatement statement = db.compileStatement(deletePhotoSql);
+ statement.bindAllArgsAsStrings(selectArgs);
+ int deleted = statement.executeUpdateDelete();
+ if (deleted > 0) {
+ changeUris.add(Photos.CONTENT_URI);
+ }
+ }
+
+ private static void deleteCascadeMetadata(SQLiteDatabase db, String photosSelect,
+ String[] selectArgs, List<Uri> changeUris) {
+ String deleteMetadataSql = nestSql(DELETE_METADATA, Metadata.PHOTO_ID, photosSelect);
+ SQLiteStatement statement = db.compileStatement(deleteMetadataSql);
+ statement.bindAllArgsAsStrings(selectArgs);
+ int deleted = statement.executeUpdateDelete();
+ if (deleted > 0) {
+ changeUris.add(Metadata.CONTENT_URI);
+ }
+ }
+}