2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.filtershow;
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;
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.ImageFilterRedEye;
36 import com.android.gallery3d.filtershow.filters.ImageFilterSaturated;
37 import com.android.gallery3d.filtershow.filters.ImageFilterShadows;
38 import com.android.gallery3d.filtershow.filters.ImageFilterSharpen;
39 import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
40 import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
41 import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
42 import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
43 import com.android.gallery3d.filtershow.imageshow.ImageCrop;
44 import com.android.gallery3d.filtershow.imageshow.ImageShow;
45 import com.android.gallery3d.filtershow.presets.ImagePreset;
46 import com.android.gallery3d.filtershow.ui.FramedTextButton;
47 import com.android.gallery3d.filtershow.ui.ImageCurves;
49 import java.util.HashMap;
50 import java.util.Vector;
52 public class PanelController implements OnClickListener {
53 private static int PANEL = 0;
54 private static int COMPONENT = 1;
55 private static int VERTICAL_MOVE = 0;
56 private static int HORIZONTAL_MOVE = 1;
57 private static final int ANIM_DURATION = 200;
58 private static final String LOGTAG = "PanelController";
61 private final View mView;
62 private final View mContainer;
63 private int mPosition = 0;
64 private final Vector<View> mSubviews = new Vector<View>();
66 public Panel(View view, View container, int position) {
68 mContainer = container;
72 public void addView(View view) {
76 public int getPosition() {
80 public ViewPropertyAnimator unselect(int newPos, int move) {
81 ViewPropertyAnimator anim = mContainer.animate();
82 mView.setSelected(false);
86 int w = mRowPanel.getWidth();
87 int h = mRowPanel.getHeight();
88 if (move == HORIZONTAL_MOVE) {
89 if (newPos > mPosition) {
95 } else if (move == VERTICAL_MOVE) {
98 anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
101 mContainer.setVisibility(View.GONE);
107 public ViewPropertyAnimator select(int oldPos, int move) {
108 mView.setSelected(true);
109 mContainer.setVisibility(View.VISIBLE);
112 ViewPropertyAnimator anim = mContainer.animate();
113 int w = mRowPanel.getWidth();
114 int h = mRowPanel.getHeight();
115 if (move == HORIZONTAL_MOVE) {
116 if (oldPos < mPosition) {
122 } else if (move == VERTICAL_MOVE) {
126 anim.setDuration(ANIM_DURATION).withLayer();
132 private final Context mContext;
133 private final View mView;
134 private final TextView mTextView;
135 private boolean mSelected = false;
136 private String mEffectName = null;
137 private int mParameterValue = 0;
138 private boolean mShowParameterValue = false;
139 private View mAspectButton = null;
140 private View mCurvesButton = null;
141 boolean firstTimeCropDisplayed = true;
143 public UtilityPanel(Context context, View view, View textView,
144 View aspectButton, View curvesButton) {
147 mTextView = (TextView) textView;
148 mAspectButton = aspectButton;
149 mCurvesButton = curvesButton;
152 public boolean selected() {
156 public void setAspectButton(FramedTextButton button, int itemId) {
157 ImageCrop imageCrop = (ImageCrop) mCurrentImage;
159 case R.id.crop_menu_1to1: {
160 String t = mContext.getString(R.string.aspect1to1_effect);
162 imageCrop.apply(1, 1);
163 imageCrop.setAspectString(t);
166 case R.id.crop_menu_4to3: {
167 String t = mContext.getString(R.string.aspect4to3_effect);
169 imageCrop.apply(4, 3);
170 imageCrop.setAspectString(t);
173 case R.id.crop_menu_3to4: {
174 String t = mContext.getString(R.string.aspect3to4_effect);
176 imageCrop.apply(3, 4);
177 imageCrop.setAspectString(t);
180 case R.id.crop_menu_5to7: {
181 String t = mContext.getString(R.string.aspect5to7_effect);
183 imageCrop.apply(5, 7);
184 imageCrop.setAspectString(t);
187 case R.id.crop_menu_7to5: {
188 String t = mContext.getString(R.string.aspect7to5_effect);
190 imageCrop.apply(7, 5);
191 imageCrop.setAspectString(t);
194 case R.id.crop_menu_none: {
195 String t = mContext.getString(R.string.aspectNone_effect);
197 imageCrop.applyClear();
198 imageCrop.setAspectString(t);
201 case R.id.crop_menu_original: {
202 String t = mContext.getString(R.string.aspectOriginal_effect);
204 imageCrop.applyOriginal();
205 imageCrop.setAspectString(t);
209 imageCrop.invalidate();
212 public void showAspectButtons() {
213 if (mAspectButton != null)
214 mAspectButton.setVisibility(View.VISIBLE);
217 public void hideAspectButtons() {
218 if (mAspectButton != null)
219 mAspectButton.setVisibility(View.GONE);
222 public void showCurvesButtons() {
223 if (mCurvesButton != null)
224 mCurvesButton.setVisibility(View.VISIBLE);
227 public void hideCurvesButtons() {
228 if (mCurvesButton != null)
229 mCurvesButton.setVisibility(View.GONE);
232 public void onNewValue(int value) {
233 mParameterValue = value;
237 public void setEffectName(String effectName) {
238 mEffectName = effectName;
239 setShowParameter(true);
242 public void setShowParameter(boolean s) {
243 mShowParameterValue = s;
247 public void updateText() {
248 String apply = mContext.getString(R.string.apply_effect);
249 if (mShowParameterValue) {
250 mTextView.setText(Html.fromHtml(apply + " " + mEffectName + " "
253 mTextView.setText(Html.fromHtml(apply + " " + mEffectName));
257 public ViewPropertyAnimator unselect() {
258 ViewPropertyAnimator anim = mView.animate();
261 int h = mRowPanel.getHeight();
263 anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
266 mView.setVisibility(View.GONE);
273 public ViewPropertyAnimator select() {
274 mView.setVisibility(View.VISIBLE);
275 int h = mRowPanel.getHeight();
279 ViewPropertyAnimator anim = mView.animate();
281 anim.setDuration(ANIM_DURATION).withLayer();
288 private final int mType;
289 private final View mView;
291 public ViewType(View view, int type) {
301 private final HashMap<View, Panel> mPanels = new HashMap<View, Panel>();
302 private final HashMap<View, ViewType> mViews = new HashMap<View, ViewType>();
303 private final Vector<View> mImageViews = new Vector<View>();
304 private View mCurrentPanel = null;
305 private View mRowPanel = null;
306 private UtilityPanel mUtilityPanel = null;
307 private ImageShow mMasterImage = null;
308 private ImageShow mCurrentImage = null;
309 private FilterShowActivity mActivity = null;
311 public void setActivity(FilterShowActivity activity) {
312 mActivity = activity;
315 public void addView(View view) {
316 view.setOnClickListener(this);
317 mViews.put(view, new ViewType(view, COMPONENT));
320 public void addPanel(View view, View container, int position) {
321 mPanels.put(view, new Panel(view, container, position));
322 view.setOnClickListener(this);
323 mViews.put(view, new ViewType(view, PANEL));
326 public void addComponent(View aPanel, View component) {
327 Panel panel = mPanels.get(aPanel);
331 panel.addView(component);
332 component.setOnClickListener(this);
333 mViews.put(component, new ViewType(component, COMPONENT));
336 public void addImageView(View view) {
337 mImageViews.add(view);
338 ImageShow imageShow = (ImageShow) view;
339 imageShow.setPanelController(this);
342 public void resetParameters() {
343 showPanel(mCurrentPanel);
344 if (mCurrentImage != null) {
345 mCurrentImage.resetParameter();
346 mCurrentImage.select();
350 public boolean onBackPressed() {
351 if (mUtilityPanel == null || !mUtilityPanel.selected()) {
354 HistoryAdapter adapter = mMasterImage.getHistory();
355 int position = adapter.undo();
356 mMasterImage.onItemClick(position);
357 showPanel(mCurrentPanel);
358 mCurrentImage.select();
362 public void onNewValue(int value) {
363 mUtilityPanel.onNewValue(value);
366 public void showParameter(boolean s) {
367 mUtilityPanel.setShowParameter(s);
370 public void setCurrentPanel(View panel) {
374 public void setRowPanel(View rowPanel) {
375 mRowPanel = rowPanel;
378 public void setUtilityPanel(Context context, View utilityPanel, View textView,
379 View aspectButton, View curvesButton) {
380 mUtilityPanel = new UtilityPanel(context, utilityPanel, textView,
381 aspectButton, curvesButton);
384 public void setMasterImage(ImageShow imageShow) {
385 mMasterImage = imageShow;
389 public void onClick(View view) {
390 ViewType type = mViews.get(view);
391 if (type.type() == PANEL) {
393 } else if (type.type() == COMPONENT) {
398 public ImageShow showImageView(int id) {
399 ImageShow image = null;
400 for (View view : mImageViews) {
401 if (view.getId() == id) {
402 view.setVisibility(View.VISIBLE);
403 image = (ImageShow) view;
405 view.setVisibility(View.GONE);
411 public void showDefaultImageView() {
412 showImageView(R.id.imageShow).setShowControls(false);
413 mMasterImage.setCurrentFilter(null);
416 public void showPanel(View view) {
417 view.setVisibility(View.VISIBLE);
418 boolean removedUtilityPanel = false;
419 Panel current = mPanels.get(mCurrentPanel);
420 if (mUtilityPanel != null && mUtilityPanel.selected()) {
421 ViewPropertyAnimator anim1 = mUtilityPanel.unselect();
422 removedUtilityPanel = true;
424 if (mCurrentPanel == view) {
425 ViewPropertyAnimator anim2 = current.select(-1, VERTICAL_MOVE);
427 showDefaultImageView();
431 if (mCurrentPanel == view) {
435 Panel panel = mPanels.get(view);
436 if (!removedUtilityPanel) {
438 if (current != null) {
439 currentPos = current.getPosition();
441 ViewPropertyAnimator anim1 = panel.select(currentPos, HORIZONTAL_MOVE);
443 if (current != null) {
444 ViewPropertyAnimator anim2 = current.unselect(panel.getPosition(), HORIZONTAL_MOVE);
448 ViewPropertyAnimator anim = panel.select(-1, VERTICAL_MOVE);
451 showDefaultImageView();
452 mCurrentPanel = view;
455 public ImagePreset getImagePreset() {
456 return mMasterImage.getImagePreset();
459 public ImageFilter setImagePreset(ImageFilter filter, String name) {
460 ImagePreset copy = new ImagePreset(getImagePreset());
462 copy.setHistoryName(name);
464 mMasterImage.setImagePreset(copy);
468 public void ensureFilter(String name) {
469 ImagePreset preset = getImagePreset();
470 ImageFilter filter = preset.getFilter(name);
471 if (filter != null) {
472 // If we already have a filter, we might still want
473 // to push it onto the history stack.
474 ImagePreset copy = new ImagePreset(getImagePreset());
475 copy.setHistoryName(name);
476 mMasterImage.setImagePreset(copy);
477 filter = copy.getFilter(name);
480 if (filter == null && name.equalsIgnoreCase(
481 mCurrentImage.getContext().getString(R.string.curvesRGB))) {
482 filter = setImagePreset(new ImageFilterCurves(), name);
484 if (filter == null && name.equalsIgnoreCase(
485 mCurrentImage.getContext().getString(R.string.tinyplanet))) {
486 filter = setImagePreset(new ImageFilterTinyPlanet(), name);
489 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.vignette))) {
490 filter = setImagePreset(new ImageFilterVignette(), name);
493 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.sharpness))) {
494 filter = setImagePreset(new ImageFilterSharpen(), name);
497 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.contrast))) {
498 filter = setImagePreset(new ImageFilterContrast(), name);
501 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.saturation))) {
502 filter = setImagePreset(new ImageFilterSaturated(), name);
505 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.bwfilter))) {
506 filter = setImagePreset(new ImageFilterBwFilter(), name);
509 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.hue))) {
510 filter = setImagePreset(new ImageFilterHue(), name);
513 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.exposure))) {
514 filter = setImagePreset(new ImageFilterExposure(), name);
517 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.vibrance))) {
518 filter = setImagePreset(new ImageFilterVibrance(), name);
521 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(
522 R.string.shadow_recovery))) {
523 filter = setImagePreset(new ImageFilterShadows(), name);
526 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.redeye))) {
527 filter = setImagePreset(new ImageFilterRedEye(), name);
530 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.wbalance))) {
531 filter = setImagePreset(new ImageFilterWBalance(), name);
533 mMasterImage.setCurrentFilter(filter);
536 private void showCurvesPopupMenu(final ImageCurves curves, final FramedTextButton anchor) {
537 PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
538 popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves, popupMenu.getMenu());
539 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
541 public boolean onMenuItemClick(MenuItem item) {
542 curves.setChannel(item.getItemId());
543 anchor.setTextFrom(item.getItemId());
550 private void showCropPopupMenu(final FramedTextButton anchor) {
551 PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
552 popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_crop, popupMenu.getMenu());
553 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
555 public boolean onMenuItemClick(MenuItem item) {
556 mUtilityPanel.setAspectButton(anchor, item.getItemId());
563 public void showComponent(View view) {
564 if (mUtilityPanel != null && !mUtilityPanel.selected()) {
565 Panel current = mPanels.get(mCurrentPanel);
566 ViewPropertyAnimator anim1 = current.unselect(-1, VERTICAL_MOVE);
568 if (mUtilityPanel != null) {
569 ViewPropertyAnimator anim2 = mUtilityPanel.select();
574 if (view.getId() == R.id.pickCurvesChannel) {
575 ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
576 showCurvesPopupMenu(curves, (FramedTextButton) view);
580 if (view.getId() == R.id.aspect) {
581 showCropPopupMenu((FramedTextButton) view);
585 if (mCurrentImage != null) {
586 mCurrentImage.unselect();
588 mUtilityPanel.hideAspectButtons();
589 mUtilityPanel.hideCurvesButtons();
590 switch (view.getId()) {
591 case R.id.tinyplanetButton: {
592 mCurrentImage = showImageView(R.id.imageTinyPlanet).setShowControls(true);
593 String ename = mCurrentImage.getContext().getString(R.string.tinyplanet);
594 mUtilityPanel.setEffectName(ename);
598 case R.id.straightenButton: {
599 mCurrentImage = showImageView(R.id.imageStraighten);
600 String ename = mCurrentImage.getContext().getString(R.string.straighten);
601 mUtilityPanel.setEffectName(ename);
604 case R.id.cropButton: {
605 mCurrentImage = showImageView(R.id.imageCrop);
606 String ename = mCurrentImage.getContext().getString(R.string.crop);
607 mUtilityPanel.setEffectName(ename);
608 mUtilityPanel.setShowParameter(false);
609 if (mCurrentImage instanceof ImageCrop && mUtilityPanel.firstTimeCropDisplayed){
610 ((ImageCrop) mCurrentImage).applyClear();
611 mUtilityPanel.firstTimeCropDisplayed = false;
613 mUtilityPanel.showAspectButtons();
616 case R.id.rotateButton: {
617 mCurrentImage = showImageView(R.id.imageRotate);
618 String ename = mCurrentImage.getContext().getString(R.string.rotate);
619 mUtilityPanel.setEffectName(ename);
622 case R.id.flipButton: {
623 mCurrentImage = showImageView(R.id.imageFlip);
624 String ename = mCurrentImage.getContext().getString(R.string.mirror);
625 mUtilityPanel.setEffectName(ename);
626 mUtilityPanel.setShowParameter(false);
629 case R.id.vignetteButton: {
630 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
631 String ename = mCurrentImage.getContext().getString(R.string.vignette);
632 mUtilityPanel.setEffectName(ename);
636 case R.id.curvesButtonRGB: {
637 ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
638 String ename = curves.getContext().getString(R.string.curvesRGB);
639 mUtilityPanel.setEffectName(ename);
640 mUtilityPanel.setShowParameter(false);
641 mUtilityPanel.showCurvesButtons();
642 mCurrentImage = curves;
646 case R.id.sharpenButton: {
647 mCurrentImage = showImageView(R.id.imageZoom).setShowControls(true);
648 String ename = mCurrentImage.getContext().getString(R.string.sharpness);
649 mUtilityPanel.setEffectName(ename);
653 case R.id.contrastButton: {
654 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
655 String ename = mCurrentImage.getContext().getString(R.string.contrast);
656 mUtilityPanel.setEffectName(ename);
660 case R.id.saturationButton: {
661 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
662 String ename = mCurrentImage.getContext().getString(R.string.saturation);
663 mUtilityPanel.setEffectName(ename);
667 case R.id.bwfilterButton: {
668 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
669 String ename = mCurrentImage.getContext().getString(R.string.bwfilter);
670 mUtilityPanel.setEffectName(ename);
674 case R.id.wbalanceButton: {
675 mCurrentImage = showImageView(R.id.imageShow).setShowControls(false);
676 String ename = mCurrentImage.getContext().getString(R.string.wbalance);
677 mUtilityPanel.setEffectName(ename);
678 mUtilityPanel.setShowParameter(false);
682 case R.id.hueButton: {
683 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
684 String ename = mCurrentImage.getContext().getString(R.string.hue);
685 mUtilityPanel.setEffectName(ename);
689 case R.id.exposureButton: {
690 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
691 String ename = mCurrentImage.getContext().getString(R.string.exposure);
692 mUtilityPanel.setEffectName(ename);
696 case R.id.vibranceButton: {
697 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
698 String ename = mCurrentImage.getContext().getString(R.string.vibrance);
699 mUtilityPanel.setEffectName(ename);
703 case R.id.shadowRecoveryButton: {
704 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
705 String ename = mCurrentImage.getContext().getString(R.string.shadow_recovery);
706 mUtilityPanel.setEffectName(ename);
710 case R.id.redEyeButton: {
711 mCurrentImage = showImageView(R.id.imageRedEyes).setShowControls(true);
712 String ename = mCurrentImage.getContext().getString(R.string.redeye);
713 mUtilityPanel.setEffectName(ename);
718 mUtilityPanel.showAspectButtons();
721 case R.id.applyEffect: {
722 if (mMasterImage.getCurrentFilter() instanceof ImageFilterTinyPlanet) {
723 mActivity.saveImage();
725 if (mCurrentImage instanceof ImageCrop) {
726 ((ImageCrop) mCurrentImage).saveAndSetPreset();
728 showPanel(mCurrentPanel);
733 mCurrentImage.select();