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