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