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