OSDN Git Service

8bae88cad140db956fc1affa1b1964b6cf4afb9f
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / FilterShowActivity.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.android.gallery3d.filtershow;
18
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.Bundle;
34 import android.util.DisplayMetrics;
35 import android.util.Log;
36 import android.util.TypedValue;
37 import android.view.Display;
38 import android.view.Menu;
39 import android.view.MenuItem;
40 import android.view.View;
41 import android.view.WindowManager;
42 import android.view.View.OnClickListener;
43 import android.widget.AdapterView;
44 import android.widget.AdapterView.OnItemClickListener;
45 import android.widget.ImageButton;
46 import android.widget.LinearLayout;
47 import android.widget.ListView;
48 import android.widget.SeekBar;
49 import android.widget.ShareActionProvider;
50 import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
51 import android.widget.Toast;
52
53 import com.android.gallery3d.R;
54 import com.android.gallery3d.data.LocalAlbum;
55 import com.android.gallery3d.filtershow.cache.ImageLoader;
56 import com.android.gallery3d.filtershow.filters.ImageFilter;
57 import com.android.gallery3d.filtershow.filters.ImageFilterBorder;
58 import com.android.gallery3d.filtershow.filters.ImageFilterContrast;
59 import com.android.gallery3d.filtershow.filters.ImageFilterExposure;
60 import com.android.gallery3d.filtershow.filters.ImageFilterFx;
61 import com.android.gallery3d.filtershow.filters.ImageFilterHue;
62 import com.android.gallery3d.filtershow.filters.ImageFilterParametricBorder;
63 import com.android.gallery3d.filtershow.filters.ImageFilterRS;
64 import com.android.gallery3d.filtershow.filters.ImageFilterSaturated;
65 import com.android.gallery3d.filtershow.filters.ImageFilterShadows;
66 import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
67 import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
68 import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
69 import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
70 import com.android.gallery3d.filtershow.imageshow.ImageBorder;
71 import com.android.gallery3d.filtershow.imageshow.ImageCrop;
72 import com.android.gallery3d.filtershow.imageshow.ImageFlip;
73 import com.android.gallery3d.filtershow.imageshow.ImageRotate;
74 import com.android.gallery3d.filtershow.imageshow.ImageShow;
75 import com.android.gallery3d.filtershow.imageshow.ImageSmallBorder;
76 import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter;
77 import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
78 import com.android.gallery3d.filtershow.imageshow.ImageWithIcon;
79 import com.android.gallery3d.filtershow.imageshow.ImageZoom;
80 import com.android.gallery3d.filtershow.presets.ImagePreset;
81 import com.android.gallery3d.filtershow.provider.SharedImageProvider;
82 import com.android.gallery3d.filtershow.tools.SaveCopyTask;
83 import com.android.gallery3d.filtershow.ui.ImageButtonTitle;
84 import com.android.gallery3d.filtershow.ui.ImageCurves;
85 import com.android.gallery3d.filtershow.ui.Spline;
86 import com.android.gallery3d.util.GalleryUtils;
87
88 import java.io.File;
89 import java.lang.ref.WeakReference;
90 import java.util.Vector;
91
92 @TargetApi(16)
93 public class FilterShowActivity extends Activity implements OnItemClickListener,
94         OnShareTargetSelectedListener {
95
96     public static final String CROP_ACTION = "com.android.camera.action.CROP";
97     public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
98     public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
99     private final PanelController mPanelController = new PanelController();
100     private ImageLoader mImageLoader = null;
101     private ImageShow mImageShow = null;
102     private ImageCurves mImageCurves = null;
103     private ImageBorder mImageBorders = null;
104     private ImageStraighten mImageStraighten = null;
105     private ImageZoom mImageZoom = null;
106     private ImageCrop mImageCrop = null;
107     private ImageRotate mImageRotate = null;
108     private ImageFlip mImageFlip = null;
109
110     private View mListFx = null;
111     private View mListBorders = null;
112     private View mListGeometry = null;
113     private View mListColors = null;
114     private View mListFilterButtons = null;
115
116     private ImageButton mFxButton = null;
117     private ImageButton mBorderButton = null;
118     private ImageButton mGeometryButton = null;
119     private ImageButton mColorsButton = null;
120
121     private ImageSmallFilter mCurrentImageSmallFilter = null;
122     private static final int SELECT_PICTURE = 1;
123     private static final String LOGTAG = "FilterShowActivity";
124     protected static final boolean ANIMATE_PANELS = true;
125     private static int mImageBorderSize = 4; // in percent
126
127     private boolean mShowingHistoryPanel = false;
128     private boolean mShowingImageStatePanel = false;
129
130     private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
131     private final Vector<View> mListViews = new Vector<View>();
132     private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>();
133
134     private ShareActionProvider mShareActionProvider;
135     private File mSharedOutputFile = null;
136
137     private boolean mSharingImage = false;
138
139     private WeakReference<ProgressDialog> mSavingProgressDialog;
140     private static final int SEEK_BAR_MAX = 600;
141
142     @Override
143     public void onCreate(Bundle savedInstanceState) {
144         super.onCreate(savedInstanceState);
145
146         ImageFilterRS.setRenderScriptContext(this);
147
148         ImageShow.setDefaultBackgroundColor(getResources().getColor(R.color.background_screen));
149         // TODO: get those values from XML.
150         ImageShow.setTextSize((int) getPixelsFromDip(12));
151         ImageShow.setTextPadding((int) getPixelsFromDip(10));
152         ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4));
153         ImageShow.setOriginalTextSize((int) getPixelsFromDip(18));
154         ImageShow.setOriginalText(getResources().getString(R.string.original_picture_text));
155         ImageButtonTitle.setTextSize((int) getPixelsFromDip(12));
156         ImageButtonTitle.setTextPadding((int) getPixelsFromDip(10));
157         ImageSmallFilter.setMargin((int) getPixelsFromDip(3));
158         ImageSmallFilter.setTextMargin((int) getPixelsFromDip(4));
159         Drawable curveHandle = getResources().getDrawable(R.drawable.camera_crop);
160         int curveHandleSize = (int) getResources().getDimension(R.dimen.crop_indicator_size);
161         Spline.setCurveHandle(curveHandle, curveHandleSize);
162         Spline.setCurveWidth((int) getPixelsFromDip(3));
163
164         setContentView(R.layout.filtershow_activity);
165         ActionBar actionBar = getActionBar();
166         actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
167         actionBar.setCustomView(R.layout.filtershow_actionbar);
168
169         actionBar.getCustomView().setOnClickListener(new OnClickListener() {
170             @Override
171             public void onClick(View view) {
172                 saveImage();
173             }
174         });
175
176         mImageLoader = new ImageLoader(this, getApplicationContext());
177
178         LinearLayout listFilters = (LinearLayout) findViewById(R.id.listFilters);
179         LinearLayout listBorders = (LinearLayout) findViewById(R.id.listBorders);
180         LinearLayout listColors = (LinearLayout) findViewById(R.id.listColorsFx);
181
182         mImageShow = (ImageShow) findViewById(R.id.imageShow);
183         mImageCurves = (ImageCurves) findViewById(R.id.imageCurves);
184         mImageBorders = (ImageBorder) findViewById(R.id.imageBorder);
185         mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
186         mImageZoom = (ImageZoom) findViewById(R.id.imageZoom);
187         mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
188         mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
189         mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
190
191         mImageViews.add(mImageShow);
192         mImageViews.add(mImageCurves);
193         mImageViews.add(mImageBorders);
194         mImageViews.add(mImageStraighten);
195         mImageViews.add(mImageZoom);
196         mImageViews.add(mImageCrop);
197         mImageViews.add(mImageRotate);
198         mImageViews.add(mImageFlip);
199
200         mListFx = findViewById(R.id.fxList);
201         mListBorders = findViewById(R.id.bordersList);
202         mListGeometry = findViewById(R.id.geometryList);
203         mListFilterButtons = findViewById(R.id.filterButtonsList);
204         mListColors = findViewById(R.id.colorsFxList);
205         mListViews.add(mListFx);
206         mListViews.add(mListBorders);
207         mListViews.add(mListGeometry);
208         mListViews.add(mListFilterButtons);
209         mListViews.add(mListColors);
210
211         mFxButton = (ImageButton) findViewById(R.id.fxButton);
212         mBorderButton = (ImageButton) findViewById(R.id.borderButton);
213         mGeometryButton = (ImageButton) findViewById(R.id.geometryButton);
214         mColorsButton = (ImageButton) findViewById(R.id.colorsButton);
215
216         mImageShow.setImageLoader(mImageLoader);
217         mImageCurves.setImageLoader(mImageLoader);
218         mImageCurves.setMaster(mImageShow);
219         mImageBorders.setImageLoader(mImageLoader);
220         mImageBorders.setMaster(mImageShow);
221         mImageStraighten.setImageLoader(mImageLoader);
222         mImageStraighten.setMaster(mImageShow);
223         mImageZoom.setImageLoader(mImageLoader);
224         mImageZoom.setMaster(mImageShow);
225         mImageCrop.setImageLoader(mImageLoader);
226         mImageCrop.setMaster(mImageShow);
227         mImageRotate.setImageLoader(mImageLoader);
228         mImageRotate.setMaster(mImageShow);
229         mImageFlip.setImageLoader(mImageLoader);
230         mImageFlip.setMaster(mImageShow);
231
232         mPanelController.addImageView(findViewById(R.id.imageShow));
233         mPanelController.addImageView(findViewById(R.id.imageCurves));
234         mPanelController.addImageView(findViewById(R.id.imageBorder));
235         mPanelController.addImageView(findViewById(R.id.imageStraighten));
236         mPanelController.addImageView(findViewById(R.id.imageCrop));
237         mPanelController.addImageView(findViewById(R.id.imageRotate));
238         mPanelController.addImageView(findViewById(R.id.imageFlip));
239         mPanelController.addImageView(findViewById(R.id.imageZoom));
240
241         mPanelController.addPanel(mFxButton, mListFx, 0);
242         mPanelController.addPanel(mBorderButton, mListBorders, 1);
243
244         mPanelController.addPanel(mGeometryButton, mListGeometry, 2);
245         mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton));
246         mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
247         mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
248         mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
249
250         mPanelController.addPanel(mColorsButton, mListColors, 3);
251
252         int[] recastIDs = {
253                 R.id.tinyplanetButton,
254                 R.id.vignetteButton,
255                 R.id.vibranceButton,
256                 R.id.contrastButton,
257                 R.id.saturationButton,
258                 R.id.wbalanceButton,
259                 R.id.hueButton,
260                 R.id.exposureButton,
261                 R.id.shadowRecoveryButton
262         };
263         ImageFilter[] filters = {
264                 new ImageFilterTinyPlanet(),
265                 new ImageFilterVignette(),
266                 new ImageFilterVibrance(),
267                 new ImageFilterContrast(),
268                 new ImageFilterSaturated(),
269                 new ImageFilterWBalance(),
270                 new ImageFilterHue(),
271                 new ImageFilterExposure(),
272                 new ImageFilterShadows()
273         };
274
275         for (int i = 0; i < filters.length; i++) {
276             ImageSmallFilter fView = new ImageSmallFilter(this);
277             View v = listColors.findViewById(recastIDs[i]);
278             int pos = listColors.indexOfChild(v);
279             listColors.removeView(v);
280
281             filters[i].setParameter(filters[i].getPreviewParameter());
282             if (v instanceof ImageButtonTitle)
283                 filters[i].setName(((ImageButtonTitle) v).getText());
284             fView.setImageFilter(filters[i]);
285             fView.setController(this);
286             fView.setImageLoader(mImageLoader);
287             fView.setId(recastIDs[i]);
288             mPanelController.addComponent(mColorsButton, fView);
289             listColors.addView(fView, pos);
290         }
291
292         int[] overlayIDs = {
293                 R.id.sharpenButton,
294                 R.id.curvesButtonRGB
295         };
296         int[] overlayBitmaps = {
297                 R.drawable.filtershow_button_colors_sharpen,
298                 R.drawable.filtershow_button_colors_curve
299         };
300         int[] overlayNames = {
301                 R.string.sharpness,
302                 R.string.curvesRGB
303         };
304
305         for (int i = 0; i < overlayIDs.length; i++) {
306             ImageWithIcon fView = new ImageWithIcon(this);
307             View v = listColors.findViewById(overlayIDs[i]);
308             int pos = listColors.indexOfChild(v);
309             listColors.removeView(v);
310             final int sid = overlayNames[i];
311             ImageFilterExposure efilter = new ImageFilterExposure() {
312                 {
313                     mName = getString(sid);
314                 }
315             };
316             efilter.setParameter(-300);
317             Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
318                     overlayBitmaps[i]);
319
320             fView.setIcon(bitmap);
321             fView.setImageFilter(efilter);
322             fView.setController(this);
323             fView.setImageLoader(mImageLoader);
324             fView.setId(overlayIDs[i]);
325             mPanelController.addComponent(mColorsButton, fView);
326             listColors.addView(fView, pos);
327         }
328
329         mPanelController.addView(findViewById(R.id.applyEffect));
330         mPanelController.addView(findViewById(R.id.pickCurvesChannel));
331         mPanelController.addView(findViewById(R.id.aspect));
332         findViewById(R.id.resetOperationsButton).setOnClickListener(
333                 createOnClickResetOperationsButton());
334
335         ListView operationsList = (ListView) findViewById(R.id.operationsList);
336         operationsList.setAdapter(mImageShow.getHistory());
337         operationsList.setOnItemClickListener(this);
338         ListView imageStateList = (ListView) findViewById(R.id.imageStateList);
339         imageStateList.setAdapter(mImageShow.getImageStateAdapter());
340         mImageLoader.setAdapter(mImageShow.getHistory());
341
342         fillListImages(listFilters);
343         fillListBorders(listBorders);
344
345         SeekBar seekBar = (SeekBar) findViewById(R.id.filterSeekBar);
346         seekBar.setMax(SEEK_BAR_MAX);
347
348         mImageShow.setSeekBar(seekBar);
349         mImageZoom.setSeekBar(seekBar);
350         mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
351         mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList),
352                 findViewById(R.id.applyEffect), findViewById(R.id.aspect),
353                 findViewById(R.id.pickCurvesChannel));
354         mPanelController.setMasterImage(mImageShow);
355         mPanelController.setCurrentPanel(mFxButton);
356         Intent intent = getIntent();
357         if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
358             getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
359         }
360
361         String data = intent.getDataString();
362         if (data != null) {
363             Uri uri = Uri.parse(data);
364             mImageLoader.loadBitmap(uri, getScreenImageSize());
365         } else {
366             pickImage();
367         }
368
369         View tinyPlanetView = listColors.findViewById(R.id.tinyplanetButton);
370
371         if (tinyPlanetView != null && !mImageLoader.isLightCycle360()) {
372             tinyPlanetView.setVisibility(View.GONE);
373         }
374
375         String action = intent.getAction();
376         if (action.equalsIgnoreCase(CROP_ACTION)) {
377             mPanelController.showComponent(findViewById(R.id.cropButton));
378         } else if (action.equalsIgnoreCase(TINY_PLANET_ACTION)) {
379             mPanelController.showComponent(findViewById(R.id.tinyplanetButton));
380         }
381     }
382
383     private int translateMainPanel(View viewPanel) {
384         int accessoryPanelWidth = viewPanel.getWidth();
385         int mainViewWidth = findViewById(R.id.mainView).getWidth();
386         int mainPanelWidth = mImageShow.getDisplayedImageBounds().width();
387         int leftOver = mainViewWidth - mainPanelWidth - accessoryPanelWidth;
388         if (leftOver < 0) {
389             return -accessoryPanelWidth;
390         }
391         return 0;
392     }
393
394     private int getScreenImageSize() {
395         DisplayMetrics metrics = new DisplayMetrics();
396         Display display = getWindowManager().getDefaultDisplay();
397         Point size = new Point();
398         display.getSize(size);
399         display.getMetrics(metrics);
400         int msize = Math.min(size.x, size.y);
401         return (133 * msize) / metrics.densityDpi;
402     }
403
404     private void showSavingProgress(String albumName) {
405         ProgressDialog progress;
406         if (mSavingProgressDialog != null) {
407             progress = mSavingProgressDialog.get();
408             if (progress != null) {
409                 progress.show();
410                 return;
411             }
412         }
413         // TODO: Allow cancellation of the saving process
414         String progressText;
415         if (albumName == null) {
416             progressText = getString(R.string.saving_image);
417         } else {
418             progressText = getString(R.string.filtershow_saving_image, albumName);
419         }
420         progress = ProgressDialog.show(this, "", progressText, true, false);
421         mSavingProgressDialog = new WeakReference<ProgressDialog>(progress);
422     }
423
424     private void hideSavingProgress() {
425         if (mSavingProgressDialog != null) {
426             ProgressDialog progress = mSavingProgressDialog.get();
427             if (progress != null)
428                 progress.dismiss();
429         }
430     }
431
432     public void completeSaveImage(Uri saveUri) {
433         if (mSharingImage && mSharedOutputFile != null) {
434             // Image saved, we unblock the content provider
435             Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
436                     Uri.encode(mSharedOutputFile.getAbsolutePath()));
437             ContentValues values = new ContentValues();
438             values.put(SharedImageProvider.PREPARE, false);
439             getContentResolver().insert(uri, values);
440         }
441         setResult(RESULT_OK, new Intent().setData(saveUri));
442         hideSavingProgress();
443         finish();
444     }
445
446     @Override
447     public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
448         // First, let's tell the SharedImageProvider that it will need to wait
449         // for the image
450         Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
451                 Uri.encode(mSharedOutputFile.getAbsolutePath()));
452         ContentValues values = new ContentValues();
453         values.put(SharedImageProvider.PREPARE, true);
454         getContentResolver().insert(uri, values);
455         mSharingImage = true;
456
457         // Process and save the image in the background.
458         showSavingProgress(null);
459         mImageShow.saveImage(this, mSharedOutputFile);
460         return true;
461     }
462
463     private Intent getDefaultShareIntent() {
464         Intent intent = new Intent(Intent.ACTION_SEND);
465         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
466         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
467         intent.setType(SharedImageProvider.MIME_TYPE);
468         mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri());
469         Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
470                 Uri.encode(mSharedOutputFile.getAbsolutePath()));
471         intent.putExtra(Intent.EXTRA_STREAM, uri);
472         return intent;
473     }
474
475     @Override
476     public boolean onCreateOptionsMenu(Menu menu) {
477         getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
478         MenuItem showHistory = menu.findItem(R.id.operationsButton);
479         if (mShowingHistoryPanel) {
480             showHistory.setTitle(R.string.hide_history_panel);
481         } else {
482             showHistory.setTitle(R.string.show_history_panel);
483         }
484         MenuItem showState = menu.findItem(R.id.showImageStateButton);
485         if (mShowingImageStatePanel) {
486             showState.setTitle(R.string.hide_imagestate_panel);
487         } else {
488             showState.setTitle(R.string.show_imagestate_panel);
489         }
490         mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
491                 .getActionProvider();
492         mShareActionProvider.setShareIntent(getDefaultShareIntent());
493         mShareActionProvider.setOnShareTargetSelectedListener(this);
494
495         MenuItem undoItem = menu.findItem(R.id.undoButton);
496         MenuItem redoItem = menu.findItem(R.id.redoButton);
497         MenuItem resetItem = menu.findItem(R.id.resetHistoryButton);
498         mImageShow.getHistory().setMenuItems(undoItem, redoItem, resetItem);
499         return true;
500     }
501
502     @Override
503     public void onPause() {
504         super.onPause();
505         if (mShareActionProvider != null) {
506             mShareActionProvider.setOnShareTargetSelectedListener(null);
507         }
508     }
509
510     @Override
511     public void onResume() {
512         super.onResume();
513         if (mShareActionProvider != null) {
514             mShareActionProvider.setOnShareTargetSelectedListener(this);
515         }
516     }
517
518     @Override
519     public boolean onOptionsItemSelected(MenuItem item) {
520         switch (item.getItemId()) {
521             case R.id.undoButton: {
522                 HistoryAdapter adapter = mImageShow.getHistory();
523                 int position = adapter.undo();
524                 mImageShow.onItemClick(position);
525                 mImageShow.showToast("Undo");
526                 invalidateViews();
527                 return true;
528             }
529             case R.id.redoButton: {
530                 HistoryAdapter adapter = mImageShow.getHistory();
531                 int position = adapter.redo();
532                 mImageShow.onItemClick(position);
533                 mImageShow.showToast("Redo");
534                 invalidateViews();
535                 return true;
536             }
537             case R.id.resetHistoryButton: {
538                 resetHistory();
539                 return true;
540             }
541             case R.id.showImageStateButton: {
542                 toggleImageStatePanel();
543                 return true;
544             }
545             case R.id.operationsButton: {
546                 toggleHistoryPanel();
547                 return true;
548             }
549             case android.R.id.home: {
550                 saveImage();
551                 return true;
552             }
553         }
554         return false;
555     }
556
557     private void fillListImages(LinearLayout listFilters) {
558         // TODO: use listview
559         // TODO: load the filters straight from the filesystem
560
561         ImageFilterFx[] fxArray = new ImageFilterFx[18];
562         int p = 0;
563
564         int[] drawid = {
565                 R.drawable.filtershow_fx_0005_punch,
566                 R.drawable.filtershow_fx_0000_vintage,
567                 R.drawable.filtershow_fx_0004_bw_contrast,
568                 R.drawable.filtershow_fx_0002_bleach,
569                 R.drawable.filtershow_fx_0001_instant,
570                 R.drawable.filtershow_fx_0007_washout,
571                 R.drawable.filtershow_fx_0003_blue_crush,
572                 R.drawable.filtershow_fx_0008_washout_color,
573                 R.drawable.filtershow_fx_0006_x_process
574         };
575
576         int[] fxNameid = {
577                 R.string.ffx_punch,
578                 R.string.ffx_vintage,
579                 R.string.ffx_bw_contrast,
580                 R.string.ffx_bleach,
581                 R.string.ffx_instant,
582                 R.string.ffx_washout,
583                 R.string.ffx_blue_crush,
584                 R.string.ffx_washout_color,
585                 R.string.ffx_x_process
586         };
587
588         ImagePreset preset = new ImagePreset(getString(R.string.history_original)); // empty
589         preset.setImageLoader(mImageLoader);
590         ImageSmallFilter filter = new ImageSmallFilter(this);
591
592         filter.setSelected(true);
593         mCurrentImageSmallFilter = filter;
594
595         filter.setImageFilter(new ImageFilterFx(null, getString(R.string.none)));
596
597         filter.setController(this);
598         filter.setImageLoader(mImageLoader);
599         listFilters.addView(filter);
600         ImageSmallFilter previousFilter = filter;
601
602         BitmapFactory.Options o = new BitmapFactory.Options();
603         o.inScaled = false;
604
605         for (int i = 0; i < drawid.length; i++) {
606             Bitmap b = BitmapFactory.decodeResource(getResources(), drawid[i], o);
607             fxArray[p++] = new ImageFilterFx(b, getString(fxNameid[i]));
608         }
609
610         for (int i = 0; i < p; i++) {
611             filter = new ImageSmallFilter(this);
612             filter.setImageFilter(fxArray[i]);
613             filter.setController(this);
614             filter.setImageLoader(mImageLoader);
615             listFilters.addView(filter);
616             previousFilter = filter;
617         }
618
619         // Default preset (original)
620         mImageShow.setImagePreset(preset);
621     }
622
623     private void fillListBorders(LinearLayout listBorders) {
624         // TODO: use listview
625         // TODO: load the borders straight from the filesystem
626         int p = 0;
627         ImageFilter[] borders = new ImageFilter[7];
628         borders[p++] = new ImageFilterBorder(null);
629
630         Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5);
631         borders[p++] = new ImageFilterBorder(npd1);
632         Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush);
633         borders[p++] = new ImageFilterBorder(npd2);
634         borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0);
635         borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize,
636                 mImageBorderSize);
637         borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0);
638         borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize,
639                 mImageBorderSize);
640
641         ImageSmallFilter previousFilter = null;
642         for (int i = 0; i < p; i++) {
643             ImageSmallBorder filter = new ImageSmallBorder(this);
644             borders[i].setName(getString(R.string.borders));
645             filter.setImageFilter(borders[i]);
646             filter.setController(this);
647             filter.setBorder(true);
648             filter.setImageLoader(mImageLoader);
649             filter.setShowTitle(false);
650             listBorders.addView(filter);
651             previousFilter = filter;
652         }
653     }
654
655     // //////////////////////////////////////////////////////////////////////////////
656     // Some utility functions
657     // TODO: finish the cleanup.
658
659     public void showOriginalViews(boolean value) {
660         for (ImageShow views : mImageViews) {
661             views.showOriginal(value);
662         }
663     }
664
665     public void invalidateViews() {
666         for (ImageShow views : mImageViews) {
667             views.invalidate();
668             views.updateImage();
669         }
670     }
671
672     public void hideListViews() {
673         for (View view : mListViews) {
674             view.setVisibility(View.GONE);
675         }
676     }
677
678     public void hideImageViews() {
679         mImageShow.setShowControls(false); // reset
680         for (View view : mImageViews) {
681             view.setVisibility(View.GONE);
682         }
683     }
684
685     public void unselectBottomPanelButtons() {
686         for (ImageButton button : mBottomPanelButtons) {
687             button.setSelected(false);
688         }
689     }
690
691     public void unselectPanelButtons(Vector<ImageButton> buttons) {
692         for (ImageButton button : buttons) {
693             button.setSelected(false);
694         }
695     }
696
697     // //////////////////////////////////////////////////////////////////////////////
698     // imageState panel...
699
700     public boolean isShowingHistoryPanel() {
701         return mShowingHistoryPanel;
702     }
703
704     private void toggleImageStatePanel() {
705         final View view = findViewById(R.id.mainPanel);
706         final View viewList = findViewById(R.id.imageStatePanel);
707
708         if (mShowingHistoryPanel) {
709             findViewById(R.id.historyPanel).setVisibility(View.INVISIBLE);
710             mShowingHistoryPanel = false;
711         }
712
713         int translate = translateMainPanel(viewList);
714         if (!mShowingImageStatePanel) {
715             mShowingImageStatePanel = true;
716             view.animate().setDuration(200).x(translate)
717                     .withLayer().withEndAction(new Runnable() {
718                         @Override
719                         public void run() {
720                             viewList.setAlpha(0);
721                             viewList.setVisibility(View.VISIBLE);
722                             viewList.animate().setDuration(100)
723                                     .alpha(1.0f).start();
724                         }
725                     }).start();
726         } else {
727             mShowingImageStatePanel = false;
728             viewList.setVisibility(View.INVISIBLE);
729             view.animate().setDuration(200).x(0).withLayer()
730                     .start();
731         }
732         invalidateOptionsMenu();
733     }
734
735     @Override
736     public void onConfigurationChanged(Configuration newConfig)
737     {
738         super.onConfigurationChanged(newConfig);
739         if (mShowingHistoryPanel) {
740             toggleHistoryPanel();
741         }
742     }
743
744     // //////////////////////////////////////////////////////////////////////////////
745     // history panel...
746
747     public void toggleHistoryPanel() {
748         final View view = findViewById(R.id.mainPanel);
749         final View viewList = findViewById(R.id.historyPanel);
750
751         if (mShowingImageStatePanel) {
752             findViewById(R.id.imageStatePanel).setVisibility(View.INVISIBLE);
753             mShowingImageStatePanel = false;
754         }
755
756         int translate = translateMainPanel(viewList);
757         if (!mShowingHistoryPanel) {
758             mShowingHistoryPanel = true;
759             view.animate().setDuration(200).x(translate)
760                     .withLayer().withEndAction(new Runnable() {
761                         @Override
762                         public void run() {
763                             viewList.setAlpha(0);
764                             viewList.setVisibility(View.VISIBLE);
765                             viewList.animate().setDuration(100)
766                                     .alpha(1.0f).start();
767                         }
768                     }).start();
769         } else {
770             mShowingHistoryPanel = false;
771             viewList.setVisibility(View.INVISIBLE);
772             view.animate().setDuration(200).x(0).withLayer()
773                     .start();
774         }
775         invalidateOptionsMenu();
776     }
777
778     private void resetHistory() {
779         HistoryAdapter adapter = mImageShow.getHistory();
780         adapter.reset();
781         ImagePreset original = new ImagePreset(adapter.getItem(0));
782         mImageShow.setImagePreset(original);
783         mPanelController.resetParameters();
784         invalidateViews();
785     }
786
787     // reset button in the history panel.
788     private OnClickListener createOnClickResetOperationsButton() {
789         return new View.OnClickListener() {
790             @Override
791             public void onClick(View v) {
792                 resetHistory();
793             }
794         };
795     }
796
797     @Override
798     public void onBackPressed() {
799         if (mPanelController.onBackPressed()) {
800             saveImage();
801         }
802     }
803
804     public void cannotLoadImage() {
805         CharSequence text = getString(R.string.cannot_load_image);
806         Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
807         toast.show();
808         finish();
809     }
810
811     // //////////////////////////////////////////////////////////////////////////////
812
813     public float getPixelsFromDip(float value) {
814         Resources r = getResources();
815         return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
816                 r.getDisplayMetrics());
817     }
818
819     public void useImagePreset(ImageSmallFilter imageSmallFilter, ImagePreset preset) {
820         if (preset == null) {
821             return;
822         }
823
824         if (mCurrentImageSmallFilter != null) {
825             mCurrentImageSmallFilter.setSelected(false);
826         }
827         mCurrentImageSmallFilter = imageSmallFilter;
828         mCurrentImageSmallFilter.setSelected(true);
829
830         ImagePreset copy = new ImagePreset(preset);
831         mImageShow.setImagePreset(copy);
832         if (preset.isFx()) {
833             // if it's an FX we rest the curve adjustment too
834             mImageCurves.resetCurve();
835         }
836         invalidateViews();
837     }
838
839     public void useImageFilter(ImageSmallFilter imageSmallFilter, ImageFilter imageFilter,
840             boolean setBorder) {
841         if (imageFilter == null) {
842             return;
843         }
844
845         if (mCurrentImageSmallFilter != null) {
846             mCurrentImageSmallFilter.setSelected(false);
847         }
848         mCurrentImageSmallFilter = imageSmallFilter;
849         mCurrentImageSmallFilter.setSelected(true);
850
851         ImagePreset oldPreset = mImageShow.getImagePreset();
852         ImagePreset copy = new ImagePreset(oldPreset);
853         // TODO: use a numerical constant instead.
854
855         copy.add(imageFilter);
856
857         mImageShow.setImagePreset(copy);
858         invalidateViews();
859     }
860
861     @Override
862     public void onItemClick(AdapterView<?> parent, View view, int position,
863             long id) {
864         mImageShow.onItemClick(position);
865         invalidateViews();
866     }
867
868     public void pickImage() {
869         Intent intent = new Intent();
870         intent.setType("image/*");
871         intent.setAction(Intent.ACTION_GET_CONTENT);
872         startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
873                 SELECT_PICTURE);
874     }
875
876     @Override
877     public void onActivityResult(int requestCode, int resultCode, Intent data) {
878         Log.v(LOGTAG, "onActivityResult");
879         if (resultCode == RESULT_OK) {
880             if (requestCode == SELECT_PICTURE) {
881                 Uri selectedImageUri = data.getData();
882                 mImageLoader.loadBitmap(selectedImageUri, getScreenImageSize());
883             }
884         }
885     }
886
887     public void saveImage() {
888         if (mImageShow.hasModifications()) {
889             // Get the name of the album, to which the image will be saved
890             File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri());
891             int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
892             String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
893             showSavingProgress(albumName);
894             mImageShow.saveImage(this, null);
895         } else {
896             finish();
897         }
898     }
899
900     static {
901         System.loadLibrary("jni_filtershow_filters");
902     }
903
904 }