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