OSDN Git Service

Added photonegative filter.
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / filtershow / PanelController.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.gallery3d.filtershow;
18
19 import android.content.Context;
20 import android.text.Html;
21 import android.view.MenuItem;
22 import android.view.View;
23 import android.view.View.OnClickListener;
24 import android.view.ViewPropertyAnimator;
25 import android.widget.PopupMenu;
26 import android.widget.TextView;
27
28 import com.android.gallery3d.R;
29 import com.android.gallery3d.filtershow.filters.ImageFilter;
30 import com.android.gallery3d.filtershow.filters.ImageFilterBwFilter;
31 import com.android.gallery3d.filtershow.filters.ImageFilterContrast;
32 import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
33 import com.android.gallery3d.filtershow.filters.ImageFilterExposure;
34 import com.android.gallery3d.filtershow.filters.ImageFilterHue;
35 import com.android.gallery3d.filtershow.filters.ImageFilterNegative;
36 import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
37 import com.android.gallery3d.filtershow.filters.ImageFilterSaturated;
38 import com.android.gallery3d.filtershow.filters.ImageFilterShadows;
39 import com.android.gallery3d.filtershow.filters.ImageFilterSharpen;
40 import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
41 import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
42 import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
43 import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
44 import com.android.gallery3d.filtershow.imageshow.ImageCrop;
45 import com.android.gallery3d.filtershow.imageshow.ImageShow;
46 import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter;
47 import com.android.gallery3d.filtershow.presets.ImagePreset;
48 import com.android.gallery3d.filtershow.ui.FramedTextButton;
49 import com.android.gallery3d.filtershow.ui.ImageCurves;
50
51 import java.util.HashMap;
52 import java.util.Vector;
53
54 public class PanelController implements OnClickListener {
55     private static int PANEL = 0;
56     private static int COMPONENT = 1;
57     private static int VERTICAL_MOVE = 0;
58     private static int HORIZONTAL_MOVE = 1;
59     private static final int ANIM_DURATION = 200;
60     private static final String LOGTAG = "PanelController";
61     private boolean mFixedAspect = false;
62
63     public void setFixedAspect(boolean t) {
64         mFixedAspect = t;
65     }
66
67     class Panel {
68         private final View mView;
69         private final View mContainer;
70         private int mPosition = 0;
71         private final Vector<View> mSubviews = new Vector<View>();
72
73         public Panel(View view, View container, int position) {
74             mView = view;
75             mContainer = container;
76             mPosition = position;
77         }
78
79         public void addView(View view) {
80             mSubviews.add(view);
81         }
82
83         public int getPosition() {
84             return mPosition;
85         }
86
87         public ViewPropertyAnimator unselect(int newPos, int move) {
88             ViewPropertyAnimator anim = mContainer.animate();
89             mView.setSelected(false);
90             mContainer.setX(0);
91             mContainer.setY(0);
92             int delta = 0;
93             int w = mRowPanel.getWidth();
94             int h = mRowPanel.getHeight();
95             if (move == HORIZONTAL_MOVE) {
96                 if (newPos > mPosition) {
97                     delta = -w;
98                 } else {
99                     delta = w;
100                 }
101                 anim.x(delta);
102             } else if (move == VERTICAL_MOVE) {
103                 anim.y(h);
104             }
105             anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
106                 @Override
107                 public void run() {
108                     mContainer.setVisibility(View.GONE);
109                 }
110             });
111             return anim;
112         }
113
114         public ViewPropertyAnimator select(int oldPos, int move) {
115             mView.setSelected(true);
116             mContainer.setVisibility(View.VISIBLE);
117             mContainer.setX(0);
118             mContainer.setY(0);
119             ViewPropertyAnimator anim = mContainer.animate();
120             int w = mRowPanel.getWidth();
121             int h = mRowPanel.getHeight();
122             if (move == HORIZONTAL_MOVE) {
123                 if (oldPos < mPosition) {
124                     mContainer.setX(w);
125                 } else {
126                     mContainer.setX(-w);
127                 }
128                 anim.x(0);
129             } else if (move == VERTICAL_MOVE) {
130                 mContainer.setY(h);
131                 anim.y(0);
132             }
133             anim.setDuration(ANIM_DURATION).withLayer();
134             return anim;
135         }
136     }
137
138     class UtilityPanel {
139         private final Context mContext;
140         private final View mView;
141         private final TextView mTextView;
142         private boolean mSelected = false;
143         private String mEffectName = null;
144         private int mParameterValue = 0;
145         private boolean mShowParameterValue = false;
146         private View mAspectButton = null;
147         private View mCurvesButton = null;
148         boolean firstTimeCropDisplayed = true;
149
150         public UtilityPanel(Context context, View view, View textView,
151                 View aspectButton, View curvesButton) {
152             mContext = context;
153             mView = view;
154             mTextView = (TextView) textView;
155             mAspectButton = aspectButton;
156             mCurvesButton = curvesButton;
157         }
158
159         public boolean selected() {
160             return mSelected;
161         }
162
163         public void setAspectButton(FramedTextButton button, int itemId) {
164             ImageCrop imageCrop = (ImageCrop) mCurrentImage;
165             switch (itemId) {
166                 case R.id.crop_menu_1to1: {
167                     String t = mContext.getString(R.string.aspect1to1_effect);
168                     button.setText(t);
169                     imageCrop.apply(1, 1);
170                     imageCrop.setAspectString(t);
171                     break;
172                 }
173                 case R.id.crop_menu_4to3: {
174                     String t = mContext.getString(R.string.aspect4to3_effect);
175                     button.setText(t);
176                     imageCrop.apply(4, 3);
177                     imageCrop.setAspectString(t);
178                     break;
179                 }
180                 case R.id.crop_menu_3to4: {
181                     String t = mContext.getString(R.string.aspect3to4_effect);
182                     button.setText(t);
183                     imageCrop.apply(3, 4);
184                     imageCrop.setAspectString(t);
185                     break;
186                 }
187                 case R.id.crop_menu_5to7: {
188                     String t = mContext.getString(R.string.aspect5to7_effect);
189                     button.setText(t);
190                     imageCrop.apply(5, 7);
191                     imageCrop.setAspectString(t);
192                     break;
193                 }
194                 case R.id.crop_menu_7to5: {
195                     String t = mContext.getString(R.string.aspect7to5_effect);
196                     button.setText(t);
197                     imageCrop.apply(7, 5);
198                     imageCrop.setAspectString(t);
199                     break;
200                 }
201                 case R.id.crop_menu_none: {
202                     String t = mContext.getString(R.string.aspectNone_effect);
203                     button.setText(t);
204                     imageCrop.applyClear();
205                     imageCrop.setAspectString(t);
206                     break;
207                 }
208                 case R.id.crop_menu_original: {
209                     String t = mContext.getString(R.string.aspectOriginal_effect);
210                     button.setText(t);
211                     imageCrop.applyOriginal();
212                     imageCrop.setAspectString(t);
213                     break;
214                 }
215             }
216             imageCrop.invalidate();
217         }
218
219         public void showAspectButtons() {
220             if (mAspectButton != null)
221                 mAspectButton.setVisibility(View.VISIBLE);
222         }
223
224         public void hideAspectButtons() {
225             if (mAspectButton != null)
226                 mAspectButton.setVisibility(View.GONE);
227         }
228
229         public void showCurvesButtons() {
230             if (mCurvesButton != null)
231                 mCurvesButton.setVisibility(View.VISIBLE);
232         }
233
234         public void hideCurvesButtons() {
235             if (mCurvesButton != null)
236                 mCurvesButton.setVisibility(View.GONE);
237         }
238
239         public void onNewValue(int value) {
240             mParameterValue = value;
241             updateText();
242         }
243
244         public void setEffectName(String effectName) {
245             mEffectName = effectName;
246             setShowParameter(true);
247         }
248
249         public void setShowParameter(boolean s) {
250             mShowParameterValue = s;
251             updateText();
252         }
253
254         public void updateText() {
255             String apply = mContext.getString(R.string.apply_effect);
256             if (mShowParameterValue) {
257                 mTextView.setText(Html.fromHtml(apply + " " + mEffectName + " "
258                         + mParameterValue));
259             } else {
260                 mTextView.setText(Html.fromHtml(apply + " " + mEffectName));
261             }
262         }
263
264         public ViewPropertyAnimator unselect() {
265             ViewPropertyAnimator anim = mView.animate();
266             mView.setX(0);
267             mView.setY(0);
268             int h = mRowPanel.getHeight();
269             anim.y(-h);
270             anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
271                 @Override
272                 public void run() {
273                     mView.setVisibility(View.GONE);
274                 }
275             });
276             mSelected = false;
277             return anim;
278         }
279
280         public ViewPropertyAnimator select() {
281             mView.setVisibility(View.VISIBLE);
282             int h = mRowPanel.getHeight();
283             mView.setX(0);
284             mView.setY(-h);
285             updateText();
286             ViewPropertyAnimator anim = mView.animate();
287             anim.y(0);
288             anim.setDuration(ANIM_DURATION).withLayer();
289             mSelected = true;
290             return anim;
291         }
292     }
293
294     class ViewType {
295         private final int mType;
296         private final View mView;
297
298         public ViewType(View view, int type) {
299             mView = view;
300             mType = type;
301         }
302
303         public int type() {
304             return mType;
305         }
306     }
307
308     private final HashMap<View, Panel> mPanels = new HashMap<View, Panel>();
309     private final HashMap<View, ViewType> mViews = new HashMap<View, ViewType>();
310     private final HashMap<String, ImageFilter> mFilters = new HashMap<String, ImageFilter>();
311     private final Vector<View> mImageViews = new Vector<View>();
312     private View mCurrentPanel = null;
313     private View mRowPanel = null;
314     private UtilityPanel mUtilityPanel = null;
315     private ImageShow mMasterImage = null;
316     private ImageShow mCurrentImage = null;
317     private FilterShowActivity mActivity = null;
318
319     public void setActivity(FilterShowActivity activity) {
320         mActivity = activity;
321     }
322
323     public void addView(View view) {
324         view.setOnClickListener(this);
325         mViews.put(view, new ViewType(view, COMPONENT));
326     }
327
328     public void addPanel(View view, View container, int position) {
329         mPanels.put(view, new Panel(view, container, position));
330         view.setOnClickListener(this);
331         mViews.put(view, new ViewType(view, PANEL));
332     }
333
334     public void addComponent(View aPanel, View component) {
335         Panel panel = mPanels.get(aPanel);
336         if (panel == null) {
337             return;
338         }
339         panel.addView(component);
340         component.setOnClickListener(this);
341         mViews.put(component, new ViewType(component, COMPONENT));
342     }
343
344     public void addFilter(ImageFilter filter) {
345         mFilters.put(filter.getName(), filter);
346     }
347
348     public void addImageView(View view) {
349         mImageViews.add(view);
350         ImageShow imageShow = (ImageShow) view;
351         imageShow.setPanelController(this);
352     }
353
354     public void resetParameters() {
355         showPanel(mCurrentPanel);
356         if (mCurrentImage != null) {
357             mCurrentImage.resetParameter();
358             mCurrentImage.select();
359         }
360     }
361
362     public boolean onBackPressed() {
363         if (mUtilityPanel == null || !mUtilityPanel.selected()) {
364             return true;
365         }
366         HistoryAdapter adapter = mMasterImage.getHistory();
367         int position = adapter.undo();
368         mMasterImage.onItemClick(position);
369         showPanel(mCurrentPanel);
370         mCurrentImage.select();
371         return false;
372     }
373
374     public void onNewValue(int value) {
375         mUtilityPanel.onNewValue(value);
376     }
377
378     public void showParameter(boolean s) {
379         mUtilityPanel.setShowParameter(s);
380     }
381
382     public void setCurrentPanel(View panel) {
383         showPanel(panel);
384     }
385
386     public void setRowPanel(View rowPanel) {
387         mRowPanel = rowPanel;
388     }
389
390     public void setUtilityPanel(Context context, View utilityPanel, View textView,
391             View aspectButton, View curvesButton) {
392         mUtilityPanel = new UtilityPanel(context, utilityPanel, textView,
393                 aspectButton, curvesButton);
394     }
395
396     public void setMasterImage(ImageShow imageShow) {
397         mMasterImage = imageShow;
398     }
399
400     @Override
401     public void onClick(View view) {
402         ViewType type = mViews.get(view);
403         if (type.type() == PANEL) {
404             showPanel(view);
405         } else if (type.type() == COMPONENT) {
406             showComponent(view);
407         }
408     }
409
410     public ImageShow showImageView(int id) {
411         ImageShow image = null;
412         for (View view : mImageViews) {
413             if (view.getId() == id) {
414                 view.setVisibility(View.VISIBLE);
415                 image = (ImageShow) view;
416             } else {
417                 view.setVisibility(View.GONE);
418             }
419         }
420         return image;
421     }
422
423     public void showDefaultImageView() {
424         showImageView(R.id.imageShow).setShowControls(false);
425         mMasterImage.setCurrentFilter(null);
426     }
427
428     public void showPanel(View view) {
429         view.setVisibility(View.VISIBLE);
430         boolean removedUtilityPanel = false;
431         Panel current = mPanels.get(mCurrentPanel);
432         if (mUtilityPanel != null && mUtilityPanel.selected()) {
433             ViewPropertyAnimator anim1 = mUtilityPanel.unselect();
434             removedUtilityPanel = true;
435             anim1.start();
436             if (mCurrentPanel == view) {
437                 ViewPropertyAnimator anim2 = current.select(-1, VERTICAL_MOVE);
438                 anim2.start();
439                 showDefaultImageView();
440             }
441         }
442
443         if (mCurrentPanel == view) {
444             return;
445         }
446
447         Panel panel = mPanels.get(view);
448         if (!removedUtilityPanel) {
449             int currentPos = -1;
450             if (current != null) {
451                 currentPos = current.getPosition();
452             }
453             ViewPropertyAnimator anim1 = panel.select(currentPos, HORIZONTAL_MOVE);
454             anim1.start();
455             if (current != null) {
456                 ViewPropertyAnimator anim2 = current.unselect(panel.getPosition(), HORIZONTAL_MOVE);
457                 anim2.start();
458             }
459         } else {
460             ViewPropertyAnimator anim = panel.select(-1, VERTICAL_MOVE);
461             anim.start();
462         }
463         showDefaultImageView();
464         mCurrentPanel = view;
465     }
466
467     public ImagePreset getImagePreset() {
468         return mMasterImage.getImagePreset();
469     }
470
471     public ImageFilter setImagePreset(ImageFilter filter, String name) {
472         ImagePreset copy = new ImagePreset(getImagePreset());
473         copy.add(filter);
474         copy.setHistoryName(name);
475         copy.setIsFx(false);
476         mMasterImage.setImagePreset(copy);
477         return filter;
478     }
479
480     public void ensureFilter(String name) {
481         ImagePreset preset = getImagePreset();
482         ImageFilter filter = preset.getFilter(name);
483         if (filter != null) {
484             // If we already have a filter, we might still want
485             // to push it onto the history stack.
486             ImagePreset copy = new ImagePreset(getImagePreset());
487             copy.setHistoryName(name);
488             mMasterImage.setImagePreset(copy);
489             filter = copy.getFilter(name);
490         }
491
492         if (filter == null) {
493             ImageFilter filterInstance = mFilters.get(name);
494             if (filterInstance != null) {
495                 try {
496                     ImageFilter newFilter = filterInstance.clone();
497                     newFilter.reset();
498                     filter = setImagePreset(newFilter, name);
499                 } catch (CloneNotSupportedException e) {
500                     e.printStackTrace();
501                 }
502             }
503         }
504         if (filter != null) {
505             mMasterImage.setCurrentFilter(filter);
506         }
507     }
508
509     private void showCurvesPopupMenu(final ImageCurves curves, final FramedTextButton anchor) {
510         PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
511         popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves, popupMenu.getMenu());
512         popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
513             @Override
514             public boolean onMenuItemClick(MenuItem item) {
515                 curves.setChannel(item.getItemId());
516                 anchor.setTextFrom(item.getItemId());
517                 return true;
518             }
519         });
520         popupMenu.show();
521     }
522
523     private void showCropPopupMenu(final FramedTextButton anchor) {
524         PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
525         popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_crop, popupMenu.getMenu());
526         popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
527             @Override
528             public boolean onMenuItemClick(MenuItem item) {
529                 mUtilityPanel.setAspectButton(anchor, item.getItemId());
530                 return true;
531             }
532         });
533         popupMenu.show();
534     }
535
536     public void showComponent(View view) {
537         if (mUtilityPanel != null && !mUtilityPanel.selected()) {
538             Panel current = mPanels.get(mCurrentPanel);
539             ViewPropertyAnimator anim1 = current.unselect(-1, VERTICAL_MOVE);
540             anim1.start();
541             if (mUtilityPanel != null) {
542                 ViewPropertyAnimator anim2 = mUtilityPanel.select();
543                 anim2.start();
544             }
545         }
546
547         if (view.getId() == R.id.pickCurvesChannel) {
548             ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
549             showCurvesPopupMenu(curves, (FramedTextButton) view);
550             return;
551         }
552
553         if (view.getId() == R.id.aspect) {
554             showCropPopupMenu((FramedTextButton) view);
555             return;
556         }
557
558         if (mCurrentImage != null) {
559             mCurrentImage.unselect();
560         }
561         mUtilityPanel.hideAspectButtons();
562         mUtilityPanel.hideCurvesButtons();
563
564         if (view instanceof ImageSmallFilter) {
565             ImageSmallFilter component = (ImageSmallFilter) view;
566             ImageFilter filter = component.getImageFilter();
567             if (filter.getEditingViewId() != 0) {
568                 mCurrentImage = showImageView(filter.getEditingViewId());
569                 mCurrentImage.setShowControls(filter.showEditingControls());
570                 String ename = mCurrentImage.getContext().getString(filter.getTextId());
571                 mUtilityPanel.setEffectName(ename);
572                 if (view.getId() == R.id.curvesButtonRGB) {
573                     // TODO: delegate to the filter / editing view the management of the
574                     // panel accessory view
575                     mUtilityPanel.showCurvesButtons();
576                 }
577                 mUtilityPanel.setShowParameter(filter.showParameterValue());
578                 ensureFilter(ename);
579                 mCurrentImage.select();
580             }
581             return;
582         }
583
584         switch (view.getId()) {
585             case R.id.tinyplanetButton: {
586                 mCurrentImage = showImageView(R.id.imageTinyPlanet).setShowControls(true);
587                 String ename = mCurrentImage.getContext().getString(R.string.tinyplanet);
588                 mUtilityPanel.setEffectName(ename);
589                 ensureFilter(ename);
590                 break;
591             }
592             case R.id.straightenButton: {
593                 mCurrentImage = showImageView(R.id.imageStraighten);
594                 String ename = mCurrentImage.getContext().getString(R.string.straighten);
595                 mUtilityPanel.setEffectName(ename);
596                 break;
597             }
598             case R.id.cropButton: {
599                 mCurrentImage = showImageView(R.id.imageCrop);
600                 String ename = mCurrentImage.getContext().getString(R.string.crop);
601                 mUtilityPanel.setEffectName(ename);
602                 mUtilityPanel.setShowParameter(false);
603                 if (mCurrentImage instanceof ImageCrop && mUtilityPanel.firstTimeCropDisplayed) {
604                     ((ImageCrop) mCurrentImage).clear();
605                     mUtilityPanel.firstTimeCropDisplayed = false;
606                 }
607                 if (!mFixedAspect) {
608                     mUtilityPanel.showAspectButtons();
609                 }
610                 break;
611             }
612             case R.id.rotateButton: {
613                 mCurrentImage = showImageView(R.id.imageRotate);
614                 String ename = mCurrentImage.getContext().getString(R.string.rotate);
615                 mUtilityPanel.setEffectName(ename);
616                 break;
617             }
618             case R.id.flipButton: {
619                 mCurrentImage = showImageView(R.id.imageFlip);
620                 String ename = mCurrentImage.getContext().getString(R.string.mirror);
621                 mUtilityPanel.setEffectName(ename);
622                 mUtilityPanel.setShowParameter(false);
623                 break;
624             }
625             case R.id.redEyeButton: {
626                 mCurrentImage = showImageView(R.id.imageRedEyes).setShowControls(true);
627                 String ename = mCurrentImage.getContext().getString(R.string.redeye);
628                 mUtilityPanel.setEffectName(ename);
629                 ensureFilter(ename);
630                 break;
631             }
632             case R.id.aspect: {
633                 mUtilityPanel.showAspectButtons();
634                 break;
635             }
636             case R.id.applyEffect: {
637                 if (mMasterImage.getCurrentFilter() instanceof ImageFilterTinyPlanet) {
638                     mActivity.saveImage();
639                 } else {
640                     if (mCurrentImage instanceof ImageCrop) {
641                         ((ImageCrop) mCurrentImage).saveAndSetPreset();
642                     }
643                     showPanel(mCurrentPanel);
644                 }
645                 break;
646             }
647         }
648         mCurrentImage.select();
649     }
650 }