2 * Copyright (C) 2012 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.gallery3d.filtershow;
19 import android.annotation.TargetApi;
20 import android.app.ActionBar;
21 import android.app.Activity;
22 import android.app.ProgressDialog;
23 import android.content.ContentValues;
24 import android.content.Intent;
25 import android.content.res.Configuration;
26 import android.content.res.Resources;
27 import android.graphics.Bitmap;
28 import android.graphics.BitmapFactory;
29 import android.graphics.Color;
30 import android.graphics.Point;
31 import android.graphics.drawable.Drawable;
32 import android.net.Uri;
33 import android.os.AsyncTask;
34 import android.os.Bundle;
35 import android.util.DisplayMetrics;
36 import android.util.Log;
37 import android.util.TypedValue;
38 import android.view.Display;
39 import android.view.Menu;
40 import android.view.MenuItem;
41 import android.view.View;
42 import android.view.View.OnClickListener;
43 import android.view.WindowManager;
44 import android.widget.AdapterView;
45 import android.widget.AdapterView.OnItemClickListener;
46 import android.widget.ImageButton;
47 import android.widget.LinearLayout;
48 import android.widget.ListView;
49 import android.widget.SeekBar;
50 import android.widget.ShareActionProvider;
51 import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
52 import android.widget.Toast;
54 import com.android.gallery3d.R;
55 import com.android.gallery3d.data.LocalAlbum;
56 import com.android.gallery3d.filtershow.cache.ImageLoader;
57 import com.android.gallery3d.filtershow.filters.ImageFilter;
58 import com.android.gallery3d.filtershow.filters.ImageFilterBorder;
59 import com.android.gallery3d.filtershow.filters.ImageFilterBwFilter;
60 import com.android.gallery3d.filtershow.filters.ImageFilterContrast;
61 import com.android.gallery3d.filtershow.filters.ImageFilterExposure;
62 import com.android.gallery3d.filtershow.filters.ImageFilterFx;
63 import com.android.gallery3d.filtershow.filters.ImageFilterHue;
64 import com.android.gallery3d.filtershow.filters.ImageFilterParametricBorder;
65 import com.android.gallery3d.filtershow.filters.ImageFilterRS;
66 import com.android.gallery3d.filtershow.filters.ImageFilterSaturated;
67 import com.android.gallery3d.filtershow.filters.ImageFilterShadows;
68 import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
69 import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
70 import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
71 import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
72 import com.android.gallery3d.filtershow.imageshow.ImageBorder;
73 import com.android.gallery3d.filtershow.imageshow.ImageCrop;
74 import com.android.gallery3d.filtershow.imageshow.ImageFlip;
75 import com.android.gallery3d.filtershow.imageshow.ImageRedEyes;
76 import com.android.gallery3d.filtershow.imageshow.ImageRotate;
77 import com.android.gallery3d.filtershow.imageshow.ImageShow;
78 import com.android.gallery3d.filtershow.imageshow.ImageSmallBorder;
79 import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter;
80 import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
81 import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet;
82 import com.android.gallery3d.filtershow.imageshow.ImageWithIcon;
83 import com.android.gallery3d.filtershow.imageshow.ImageZoom;
84 import com.android.gallery3d.filtershow.presets.ImagePreset;
85 import com.android.gallery3d.filtershow.provider.SharedImageProvider;
86 import com.android.gallery3d.filtershow.tools.SaveCopyTask;
87 import com.android.gallery3d.filtershow.ui.FramedTextButton;
88 import com.android.gallery3d.filtershow.ui.ImageButtonTitle;
89 import com.android.gallery3d.filtershow.ui.ImageCurves;
90 import com.android.gallery3d.filtershow.ui.Spline;
91 import com.android.gallery3d.util.GalleryUtils;
94 import java.lang.ref.WeakReference;
95 import java.util.Vector;
98 public class FilterShowActivity extends Activity implements OnItemClickListener,
99 OnShareTargetSelectedListener {
101 public static final String CROP_ACTION = "com.android.camera.action.EDITOR_CROP";
102 public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
103 public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
104 private final PanelController mPanelController = new PanelController();
105 private ImageLoader mImageLoader = null;
106 private ImageShow mImageShow = null;
107 private ImageCurves mImageCurves = null;
108 private ImageBorder mImageBorders = null;
109 private ImageRedEyes mImageRedEyes = null;
110 private ImageStraighten mImageStraighten = null;
111 private ImageZoom mImageZoom = null;
112 private ImageCrop mImageCrop = null;
113 private ImageRotate mImageRotate = null;
114 private ImageFlip mImageFlip = null;
115 private ImageTinyPlanet mImageTinyPlanet = null;
117 private View mListFx = null;
118 private View mListBorders = null;
119 private View mListGeometry = null;
120 private View mListColors = null;
121 private View mListFilterButtons = null;
122 private View mSaveButton = null;
124 private ImageButton mFxButton = null;
125 private ImageButton mBorderButton = null;
126 private ImageButton mGeometryButton = null;
127 private ImageButton mColorsButton = null;
129 private ImageSmallFilter mCurrentImageSmallFilter = null;
130 private static final int SELECT_PICTURE = 1;
131 private static final String LOGTAG = "FilterShowActivity";
132 protected static final boolean ANIMATE_PANELS = true;
133 private static int mImageBorderSize = 4; // in percent
135 private boolean mShowingHistoryPanel = false;
136 private boolean mShowingImageStatePanel = false;
138 private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
139 private final Vector<View> mListViews = new Vector<View>();
140 private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>();
142 private ShareActionProvider mShareActionProvider;
143 private File mSharedOutputFile = null;
145 private boolean mSharingImage = false;
147 private WeakReference<ProgressDialog> mSavingProgressDialog;
148 private static final int SEEK_BAR_MAX = 600;
150 private LoadBitmapTask mLoadBitmapTask;
151 private ImageSmallFilter mNullFxFilter;
152 private ImageSmallFilter mNullBorderFilter;
155 public void onCreate(Bundle savedInstanceState) {
156 super.onCreate(savedInstanceState);
158 ImageFilterRS.setRenderScriptContext(this);
160 ImageShow.setDefaultBackgroundColor(getResources().getColor(R.color.background_screen));
161 ImageSmallFilter.setDefaultBackgroundColor(getResources().getColor(
162 R.color.background_main_toolbar));
163 // TODO: get those values from XML.
164 ImageZoom.setZoomedSize(getPixelsFromDip(256));
165 FramedTextButton.setTextSize((int) getPixelsFromDip(14));
166 FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4));
167 FramedTextButton.setTriangleSize((int) getPixelsFromDip(10));
168 ImageShow.setTextSize((int) getPixelsFromDip(12));
169 ImageShow.setTextPadding((int) getPixelsFromDip(10));
170 ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4));
171 ImageShow.setOriginalTextSize((int) getPixelsFromDip(18));
172 ImageShow.setOriginalText(getResources().getString(R.string.original_picture_text));
173 ImageButtonTitle.setTextSize((int) getPixelsFromDip(12));
174 ImageButtonTitle.setTextPadding((int) getPixelsFromDip(10));
175 ImageSmallFilter.setMargin((int) getPixelsFromDip(3));
176 ImageSmallFilter.setTextMargin((int) getPixelsFromDip(4));
177 Drawable curveHandle = getResources().getDrawable(R.drawable.camera_crop);
178 int curveHandleSize = (int) getResources().getDimension(R.dimen.crop_indicator_size);
179 Spline.setCurveHandle(curveHandle, curveHandleSize);
180 Spline.setCurveWidth((int) getPixelsFromDip(3));
182 setContentView(R.layout.filtershow_activity);
183 ActionBar actionBar = getActionBar();
184 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
185 actionBar.setCustomView(R.layout.filtershow_actionbar);
187 mSaveButton = actionBar.getCustomView();
188 mSaveButton.setOnClickListener(new OnClickListener() {
190 public void onClick(View view) {
195 mImageLoader = new ImageLoader(this, getApplicationContext());
197 LinearLayout listFilters = (LinearLayout) findViewById(R.id.listFilters);
198 LinearLayout listBorders = (LinearLayout) findViewById(R.id.listBorders);
199 LinearLayout listColors = (LinearLayout) findViewById(R.id.listColorsFx);
201 mImageShow = (ImageShow) findViewById(R.id.imageShow);
202 mImageCurves = (ImageCurves) findViewById(R.id.imageCurves);
203 mImageBorders = (ImageBorder) findViewById(R.id.imageBorder);
204 mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
205 mImageZoom = (ImageZoom) findViewById(R.id.imageZoom);
206 mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
207 mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
208 mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
209 mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet);
210 mImageRedEyes = (ImageRedEyes) findViewById(R.id.imageRedEyes);
212 mImageCrop.setAspectTextSize((int) getPixelsFromDip(18));
213 ImageCrop.setTouchTolerance((int) getPixelsFromDip(25));
214 ImageCrop.setMinCropSize((int) getPixelsFromDip(55));
215 mImageViews.add(mImageShow);
216 mImageViews.add(mImageCurves);
217 mImageViews.add(mImageBorders);
218 mImageViews.add(mImageStraighten);
219 mImageViews.add(mImageZoom);
220 mImageViews.add(mImageCrop);
221 mImageViews.add(mImageRotate);
222 mImageViews.add(mImageFlip);
223 mImageViews.add(mImageTinyPlanet);
224 mImageViews.add(mImageRedEyes);
225 for (ImageShow imageShow : mImageViews) {
226 mImageLoader.addCacheListener(imageShow);
229 mListFx = findViewById(R.id.fxList);
230 mListBorders = findViewById(R.id.bordersList);
231 mListGeometry = findViewById(R.id.geometryList);
232 mListFilterButtons = findViewById(R.id.filterButtonsList);
233 mListColors = findViewById(R.id.colorsFxList);
234 mListViews.add(mListFx);
235 mListViews.add(mListBorders);
236 mListViews.add(mListGeometry);
237 mListViews.add(mListFilterButtons);
238 mListViews.add(mListColors);
240 mFxButton = (ImageButton) findViewById(R.id.fxButton);
241 mBorderButton = (ImageButton) findViewById(R.id.borderButton);
242 mGeometryButton = (ImageButton) findViewById(R.id.geometryButton);
243 mColorsButton = (ImageButton) findViewById(R.id.colorsButton);
245 mImageShow.setImageLoader(mImageLoader);
246 mImageCurves.setImageLoader(mImageLoader);
247 mImageCurves.setMaster(mImageShow);
248 mImageBorders.setImageLoader(mImageLoader);
249 mImageBorders.setMaster(mImageShow);
250 mImageStraighten.setImageLoader(mImageLoader);
251 mImageStraighten.setMaster(mImageShow);
252 mImageZoom.setImageLoader(mImageLoader);
253 mImageZoom.setMaster(mImageShow);
254 mImageCrop.setImageLoader(mImageLoader);
255 mImageCrop.setMaster(mImageShow);
256 mImageRotate.setImageLoader(mImageLoader);
257 mImageRotate.setMaster(mImageShow);
258 mImageFlip.setImageLoader(mImageLoader);
259 mImageFlip.setMaster(mImageShow);
260 mImageTinyPlanet.setImageLoader(mImageLoader);
261 mImageTinyPlanet.setMaster(mImageShow);
262 mImageRedEyes.setImageLoader(mImageLoader);
263 mImageRedEyes.setMaster(mImageShow);
265 mPanelController.setActivity(this);
267 mPanelController.addImageView(findViewById(R.id.imageShow));
268 mPanelController.addImageView(findViewById(R.id.imageCurves));
269 mPanelController.addImageView(findViewById(R.id.imageBorder));
270 mPanelController.addImageView(findViewById(R.id.imageStraighten));
271 mPanelController.addImageView(findViewById(R.id.imageCrop));
272 mPanelController.addImageView(findViewById(R.id.imageRotate));
273 mPanelController.addImageView(findViewById(R.id.imageFlip));
274 mPanelController.addImageView(findViewById(R.id.imageZoom));
275 mPanelController.addImageView(findViewById(R.id.imageTinyPlanet));
276 mPanelController.addImageView(findViewById(R.id.imageRedEyes));
278 mPanelController.addPanel(mFxButton, mListFx, 0);
279 mPanelController.addPanel(mBorderButton, mListBorders, 1);
281 mPanelController.addPanel(mGeometryButton, mListGeometry, 2);
282 mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton));
283 mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
284 mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
285 mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
286 mPanelController.addComponent(mGeometryButton, findViewById(R.id.redEyeButton));
288 mPanelController.addPanel(mColorsButton, mListColors, 3);
291 R.id.tinyplanetButton,
295 R.id.saturationButton,
300 R.id.shadowRecoveryButton
302 ImageFilter[] filters = {
303 new ImageFilterTinyPlanet(),
304 new ImageFilterVignette(),
305 new ImageFilterVibrance(),
306 new ImageFilterContrast(),
307 new ImageFilterSaturated(),
308 new ImageFilterBwFilter(),
309 new ImageFilterWBalance(),
310 new ImageFilterHue(),
311 new ImageFilterExposure(),
312 new ImageFilterShadows()
315 for (int i = 0; i < filters.length; i++) {
316 ImageSmallFilter fView = new ImageSmallFilter(this);
317 View v = listColors.findViewById(recastIDs[i]);
318 int pos = listColors.indexOfChild(v);
319 listColors.removeView(v);
321 filters[i].setParameter(filters[i].getPreviewParameter());
322 if (v instanceof ImageButtonTitle)
323 filters[i].setName(((ImageButtonTitle) v).getText());
324 fView.setImageFilter(filters[i]);
325 fView.setController(this);
326 fView.setImageLoader(mImageLoader);
327 fView.setId(recastIDs[i]);
328 mPanelController.addComponent(mColorsButton, fView);
329 listColors.addView(fView, pos);
336 int[] overlayBitmaps = {
337 R.drawable.filtershow_button_colors_sharpen,
338 R.drawable.filtershow_button_colors_curve
340 int[] overlayNames = {
345 for (int i = 0; i < overlayIDs.length; i++) {
346 ImageWithIcon fView = new ImageWithIcon(this);
347 View v = listColors.findViewById(overlayIDs[i]);
348 int pos = listColors.indexOfChild(v);
349 listColors.removeView(v);
350 final int sid = overlayNames[i];
351 ImageFilterExposure efilter = new ImageFilterExposure() {
353 mName = getString(sid);
356 efilter.setParameter(-300);
357 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
360 fView.setIcon(bitmap);
361 fView.setImageFilter(efilter);
362 fView.setController(this);
363 fView.setImageLoader(mImageLoader);
364 fView.setId(overlayIDs[i]);
365 mPanelController.addComponent(mColorsButton, fView);
366 listColors.addView(fView, pos);
369 mPanelController.addView(findViewById(R.id.applyEffect));
370 mPanelController.addView(findViewById(R.id.pickCurvesChannel));
371 mPanelController.addView(findViewById(R.id.aspect));
372 findViewById(R.id.resetOperationsButton).setOnClickListener(
373 createOnClickResetOperationsButton());
375 ListView operationsList = (ListView) findViewById(R.id.operationsList);
376 operationsList.setAdapter(mImageShow.getHistory());
377 operationsList.setOnItemClickListener(this);
378 ListView imageStateList = (ListView) findViewById(R.id.imageStateList);
379 imageStateList.setAdapter(mImageShow.getImageStateAdapter());
380 mImageLoader.setAdapter(mImageShow.getHistory());
382 fillListImages(listFilters);
383 fillListBorders(listBorders);
385 SeekBar seekBar = (SeekBar) findViewById(R.id.filterSeekBar);
386 seekBar.setMax(SEEK_BAR_MAX);
388 mImageShow.setSeekBar(seekBar);
389 mImageZoom.setSeekBar(seekBar);
390 mImageTinyPlanet.setSeekBar(seekBar);
391 mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
392 mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList),
393 findViewById(R.id.applyEffect), findViewById(R.id.aspect),
394 findViewById(R.id.pickCurvesChannel));
395 mPanelController.setMasterImage(mImageShow);
396 mPanelController.setCurrentPanel(mFxButton);
397 Intent intent = getIntent();
398 if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
399 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
402 if (intent.getData() != null) {
403 startLoadBitmap(intent.getData());
408 String action = intent.getAction();
409 if (action.equalsIgnoreCase(CROP_ACTION)) {
410 mPanelController.showComponent(findViewById(R.id.cropButton));
411 } else if (action.equalsIgnoreCase(TINY_PLANET_ACTION)) {
412 mPanelController.showComponent(findViewById(R.id.tinyplanetButton));
416 private void startLoadBitmap(Uri uri) {
417 final View filters = findViewById(R.id.filtersPanel);
418 final View loading = findViewById(R.id.loading);
419 loading.setVisibility(View.VISIBLE);
420 filters.setVisibility(View.INVISIBLE);
421 View tinyPlanetView = findViewById(R.id.tinyplanetButton);
422 if (tinyPlanetView != null) {
423 tinyPlanetView.setVisibility(View.GONE);
425 mLoadBitmapTask = new LoadBitmapTask(tinyPlanetView);
426 mLoadBitmapTask.execute(uri);
429 private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> {
430 View mTinyPlanetButton;
433 public LoadBitmapTask(View button) {
434 mTinyPlanetButton = button;
435 mBitmapSize = getScreenImageSize();
439 protected Boolean doInBackground(Uri... params) {
440 if (!mImageLoader.loadBitmap(params[0], mBitmapSize)) {
443 publishProgress(mImageLoader.queryLightCycle360());
448 protected void onProgressUpdate(Boolean... values) {
449 super.onProgressUpdate(values);
452 final View filters = findViewById(R.id.filtersPanel);
453 final View loading = findViewById(R.id.loading);
454 loading.setVisibility(View.GONE);
455 filters.setVisibility(View.VISIBLE);
457 mTinyPlanetButton.setVisibility(View.VISIBLE);
462 protected void onPostExecute(Boolean result) {
470 mLoadBitmapTask = null;
471 super.onPostExecute(result);
477 protected void onDestroy() {
478 if (mLoadBitmapTask != null) {
479 mLoadBitmapTask.cancel(false);
484 private int translateMainPanel(View viewPanel) {
485 int accessoryPanelWidth = viewPanel.getWidth();
486 int mainViewWidth = findViewById(R.id.mainView).getWidth();
487 int mainPanelWidth = mImageShow.getDisplayedImageBounds().width();
488 if (mainPanelWidth == 0) {
489 mainPanelWidth = mainViewWidth;
491 int filtersPanelWidth = findViewById(R.id.filtersPanel).getWidth();
492 if (mainPanelWidth < filtersPanelWidth) {
493 mainPanelWidth = filtersPanelWidth;
495 int leftOver = mainViewWidth - mainPanelWidth - accessoryPanelWidth;
497 return -accessoryPanelWidth;
502 private int getScreenImageSize() {
503 DisplayMetrics metrics = new DisplayMetrics();
504 Display display = getWindowManager().getDefaultDisplay();
505 Point size = new Point();
506 display.getSize(size);
507 display.getMetrics(metrics);
508 int msize = Math.min(size.x, size.y);
509 return (133 * msize) / metrics.densityDpi;
512 private void showSavingProgress(String albumName) {
513 ProgressDialog progress;
514 if (mSavingProgressDialog != null) {
515 progress = mSavingProgressDialog.get();
516 if (progress != null) {
521 // TODO: Allow cancellation of the saving process
523 if (albumName == null) {
524 progressText = getString(R.string.saving_image);
526 progressText = getString(R.string.filtershow_saving_image, albumName);
528 progress = ProgressDialog.show(this, "", progressText, true, false);
529 mSavingProgressDialog = new WeakReference<ProgressDialog>(progress);
532 private void hideSavingProgress() {
533 if (mSavingProgressDialog != null) {
534 ProgressDialog progress = mSavingProgressDialog.get();
535 if (progress != null)
540 public void completeSaveImage(Uri saveUri) {
541 if (mSharingImage && mSharedOutputFile != null) {
542 // Image saved, we unblock the content provider
543 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
544 Uri.encode(mSharedOutputFile.getAbsolutePath()));
545 ContentValues values = new ContentValues();
546 values.put(SharedImageProvider.PREPARE, false);
547 getContentResolver().insert(uri, values);
549 setResult(RESULT_OK, new Intent().setData(saveUri));
550 hideSavingProgress();
555 public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
556 // First, let's tell the SharedImageProvider that it will need to wait
558 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
559 Uri.encode(mSharedOutputFile.getAbsolutePath()));
560 ContentValues values = new ContentValues();
561 values.put(SharedImageProvider.PREPARE, true);
562 getContentResolver().insert(uri, values);
563 mSharingImage = true;
565 // Process and save the image in the background.
566 showSavingProgress(null);
567 mImageShow.saveImage(this, mSharedOutputFile);
571 private Intent getDefaultShareIntent() {
572 Intent intent = new Intent(Intent.ACTION_SEND);
573 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
574 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
575 intent.setType(SharedImageProvider.MIME_TYPE);
576 mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri());
577 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
578 Uri.encode(mSharedOutputFile.getAbsolutePath()));
579 intent.putExtra(Intent.EXTRA_STREAM, uri);
584 public boolean onCreateOptionsMenu(Menu menu) {
585 getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
586 MenuItem showHistory = menu.findItem(R.id.operationsButton);
587 if (mShowingHistoryPanel) {
588 showHistory.setTitle(R.string.hide_history_panel);
590 showHistory.setTitle(R.string.show_history_panel);
592 MenuItem showState = menu.findItem(R.id.showImageStateButton);
593 if (mShowingImageStatePanel) {
594 showState.setTitle(R.string.hide_imagestate_panel);
596 showState.setTitle(R.string.show_imagestate_panel);
598 mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
599 .getActionProvider();
600 mShareActionProvider.setShareIntent(getDefaultShareIntent());
601 mShareActionProvider.setOnShareTargetSelectedListener(this);
603 MenuItem undoItem = menu.findItem(R.id.undoButton);
604 MenuItem redoItem = menu.findItem(R.id.redoButton);
605 MenuItem resetItem = menu.findItem(R.id.resetHistoryButton);
606 mImageShow.getHistory().setMenuItems(undoItem, redoItem, resetItem);
611 public void onPause() {
613 if (mShareActionProvider != null) {
614 mShareActionProvider.setOnShareTargetSelectedListener(null);
619 public void onResume() {
621 if (mShareActionProvider != null) {
622 mShareActionProvider.setOnShareTargetSelectedListener(this);
627 public boolean onOptionsItemSelected(MenuItem item) {
628 switch (item.getItemId()) {
629 case R.id.undoButton: {
630 HistoryAdapter adapter = mImageShow.getHistory();
631 int position = adapter.undo();
632 mImageShow.onItemClick(position);
633 mImageShow.showToast("Undo");
637 case R.id.redoButton: {
638 HistoryAdapter adapter = mImageShow.getHistory();
639 int position = adapter.redo();
640 mImageShow.onItemClick(position);
641 mImageShow.showToast("Redo");
645 case R.id.resetHistoryButton: {
649 case R.id.showImageStateButton: {
650 toggleImageStatePanel();
653 case R.id.operationsButton: {
654 toggleHistoryPanel();
657 case android.R.id.home: {
665 public void enableSave(boolean enable) {
666 if (mSaveButton != null)
667 mSaveButton.setEnabled(enable);
670 private void fillListImages(LinearLayout listFilters) {
671 // TODO: use listview
672 // TODO: load the filters straight from the filesystem
674 ImageFilterFx[] fxArray = new ImageFilterFx[18];
678 R.drawable.filtershow_fx_0005_punch,
679 R.drawable.filtershow_fx_0000_vintage,
680 R.drawable.filtershow_fx_0004_bw_contrast,
681 R.drawable.filtershow_fx_0002_bleach,
682 R.drawable.filtershow_fx_0001_instant,
683 R.drawable.filtershow_fx_0007_washout,
684 R.drawable.filtershow_fx_0003_blue_crush,
685 R.drawable.filtershow_fx_0008_washout_color,
686 R.drawable.filtershow_fx_0006_x_process
691 R.string.ffx_vintage,
692 R.string.ffx_bw_contrast,
694 R.string.ffx_instant,
695 R.string.ffx_washout,
696 R.string.ffx_blue_crush,
697 R.string.ffx_washout_color,
698 R.string.ffx_x_process
701 ImagePreset preset = new ImagePreset(getString(R.string.history_original)); // empty
702 preset.setImageLoader(mImageLoader);
703 mNullFxFilter = new ImageSmallFilter(this);
705 mNullFxFilter.setSelected(true);
706 mCurrentImageSmallFilter = mNullFxFilter;
708 mNullFxFilter.setImageFilter(new ImageFilterFx(null, getString(R.string.none)));
710 mNullFxFilter.setController(this);
711 mNullFxFilter.setImageLoader(mImageLoader);
712 listFilters.addView(mNullFxFilter);
713 ImageSmallFilter previousFilter = mNullFxFilter;
715 BitmapFactory.Options o = new BitmapFactory.Options();
718 for (int i = 0; i < drawid.length; i++) {
719 Bitmap b = BitmapFactory.decodeResource(getResources(), drawid[i], o);
720 fxArray[p++] = new ImageFilterFx(b, getString(fxNameid[i]));
722 ImageSmallFilter filter;
723 for (int i = 0; i < p; i++) {
724 filter = new ImageSmallFilter(this);
725 filter.setImageFilter(fxArray[i]);
726 filter.setController(this);
727 filter.setNulfilter(mNullFxFilter);
728 filter.setImageLoader(mImageLoader);
729 listFilters.addView(filter);
730 previousFilter = filter;
733 // Default preset (original)
734 mImageShow.setImagePreset(preset);
737 private void fillListBorders(LinearLayout listBorders) {
738 // TODO: use listview
739 // TODO: load the borders straight from the filesystem
741 ImageFilter[] borders = new ImageFilter[12];
742 borders[p++] = new ImageFilterBorder(null);
744 Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5);
745 borders[p++] = new ImageFilterBorder(npd1);
746 Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush);
747 borders[p++] = new ImageFilterBorder(npd2);
748 Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_grunge);
749 borders[p++] = new ImageFilterBorder(npd3);
750 Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_sumi_e);
751 borders[p++] = new ImageFilterBorder(npd4);
752 Drawable npd5 = getResources().getDrawable(R.drawable.filtershow_border_tape);
753 borders[p++] = new ImageFilterBorder(npd5);
754 borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0);
755 borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize,
757 borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0);
758 borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize,
760 int creamColor = Color.argb(255, 237, 237, 227);
761 borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize, 0);
762 borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize,
765 ImageSmallFilter previousFilter = null;
766 for (int i = 0; i < p; i++) {
767 ImageSmallBorder filter = new ImageSmallBorder(this);
768 if (i == 0) { // save the first to reset it
769 mNullBorderFilter = filter;
771 filter.setNulfilter(mNullBorderFilter);
773 borders[i].setName(getString(R.string.borders));
774 filter.setImageFilter(borders[i]);
775 filter.setController(this);
776 filter.setBorder(true);
777 filter.setImageLoader(mImageLoader);
778 filter.setShowTitle(false);
779 listBorders.addView(filter);
780 previousFilter = filter;
784 // //////////////////////////////////////////////////////////////////////////////
785 // Some utility functions
786 // TODO: finish the cleanup.
788 public void showOriginalViews(boolean value) {
789 for (ImageShow views : mImageViews) {
790 views.showOriginal(value);
794 public void invalidateViews() {
795 for (ImageShow views : mImageViews) {
801 public void hideListViews() {
802 for (View view : mListViews) {
803 view.setVisibility(View.GONE);
807 public void hideImageViews() {
808 mImageShow.setShowControls(false); // reset
809 for (View view : mImageViews) {
810 view.setVisibility(View.GONE);
814 public void unselectBottomPanelButtons() {
815 for (ImageButton button : mBottomPanelButtons) {
816 button.setSelected(false);
820 public void unselectPanelButtons(Vector<ImageButton> buttons) {
821 for (ImageButton button : buttons) {
822 button.setSelected(false);
826 // //////////////////////////////////////////////////////////////////////////////
827 // imageState panel...
829 public boolean isShowingHistoryPanel() {
830 return mShowingHistoryPanel;
833 private void toggleImageStatePanel() {
834 final View view = findViewById(R.id.mainPanel);
835 final View viewList = findViewById(R.id.imageStatePanel);
837 if (mShowingHistoryPanel) {
838 findViewById(R.id.historyPanel).setVisibility(View.INVISIBLE);
839 mShowingHistoryPanel = false;
842 int translate = translateMainPanel(viewList);
843 if (!mShowingImageStatePanel) {
844 mShowingImageStatePanel = true;
845 view.animate().setDuration(200).x(translate)
846 .withLayer().withEndAction(new Runnable() {
849 viewList.setAlpha(0);
850 viewList.setVisibility(View.VISIBLE);
851 viewList.animate().setDuration(100)
852 .alpha(1.0f).start();
856 mShowingImageStatePanel = false;
857 viewList.setVisibility(View.INVISIBLE);
858 view.animate().setDuration(200).x(0).withLayer()
861 invalidateOptionsMenu();
865 public void onConfigurationChanged(Configuration newConfig)
867 super.onConfigurationChanged(newConfig);
868 if (mShowingHistoryPanel) {
869 toggleHistoryPanel();
873 // //////////////////////////////////////////////////////////////////////////////
876 public void toggleHistoryPanel() {
877 final View view = findViewById(R.id.mainPanel);
878 final View viewList = findViewById(R.id.historyPanel);
880 if (mShowingImageStatePanel) {
881 findViewById(R.id.imageStatePanel).setVisibility(View.INVISIBLE);
882 mShowingImageStatePanel = false;
885 int translate = translateMainPanel(viewList);
886 if (!mShowingHistoryPanel) {
887 mShowingHistoryPanel = true;
888 view.animate().setDuration(200).x(translate)
889 .withLayer().withEndAction(new Runnable() {
892 viewList.setAlpha(0);
893 viewList.setVisibility(View.VISIBLE);
894 viewList.animate().setDuration(100)
895 .alpha(1.0f).start();
899 mShowingHistoryPanel = false;
900 viewList.setVisibility(View.INVISIBLE);
901 view.animate().setDuration(200).x(0).withLayer()
904 invalidateOptionsMenu();
907 private void resetHistory() {
908 mNullFxFilter.onClick(mNullFxFilter);
909 mNullBorderFilter.onClick(mNullBorderFilter);
911 HistoryAdapter adapter = mImageShow.getHistory();
913 ImagePreset original = new ImagePreset(adapter.getItem(0));
914 mImageShow.setImagePreset(original);
915 mPanelController.resetParameters();
919 // reset button in the history panel.
920 private OnClickListener createOnClickResetOperationsButton() {
921 return new View.OnClickListener() {
923 public void onClick(View v) {
931 public void onBackPressed() {
932 if (mPanelController.onBackPressed()) {
937 public void cannotLoadImage() {
938 CharSequence text = getString(R.string.cannot_load_image);
939 Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
944 // //////////////////////////////////////////////////////////////////////////////
946 public float getPixelsFromDip(float value) {
947 Resources r = getResources();
948 return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
949 r.getDisplayMetrics());
952 public void useImagePreset(ImageSmallFilter imageSmallFilter, ImagePreset preset) {
953 if (preset == null) {
957 if (mCurrentImageSmallFilter != null) {
958 mCurrentImageSmallFilter.setSelected(false);
960 mCurrentImageSmallFilter = imageSmallFilter;
961 mCurrentImageSmallFilter.setSelected(true);
963 ImagePreset copy = new ImagePreset(preset);
964 mImageShow.setImagePreset(copy);
966 // if it's an FX we rest the curve adjustment too
967 mImageCurves.resetCurve();
972 public void useImageFilter(ImageSmallFilter imageSmallFilter, ImageFilter imageFilter,
974 if (imageFilter == null) {
978 if (mCurrentImageSmallFilter != null) {
979 mCurrentImageSmallFilter.setSelected(false);
981 mCurrentImageSmallFilter = imageSmallFilter;
982 mCurrentImageSmallFilter.setSelected(true);
984 ImagePreset oldPreset = mImageShow.getImagePreset();
985 ImagePreset copy = new ImagePreset(oldPreset);
986 // TODO: use a numerical constant instead.
988 copy.add(imageFilter);
990 mImageShow.setImagePreset(copy);
995 public void onItemClick(AdapterView<?> parent, View view, int position,
997 mImageShow.onItemClick(position);
1001 public void pickImage() {
1002 Intent intent = new Intent();
1003 intent.setType("image/*");
1004 intent.setAction(Intent.ACTION_GET_CONTENT);
1005 startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
1010 public void onActivityResult(int requestCode, int resultCode, Intent data) {
1011 Log.v(LOGTAG, "onActivityResult");
1012 if (resultCode == RESULT_OK) {
1013 if (requestCode == SELECT_PICTURE) {
1014 Uri selectedImageUri = data.getData();
1015 startLoadBitmap(selectedImageUri);
1020 public void saveImage() {
1021 if (mImageShow.hasModifications()) {
1022 // Get the name of the album, to which the image will be saved
1023 File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri());
1024 int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
1025 String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
1026 showSavingProgress(albumName);
1027 mImageShow.saveImage(this, null);
1034 System.loadLibrary("jni_filtershow_filters");