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