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.ImageFilterContrast;
31 import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
32 import com.android.gallery3d.filtershow.filters.ImageFilterExposure;
33 import com.android.gallery3d.filtershow.filters.ImageFilterHue;
34 import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
35 import com.android.gallery3d.filtershow.filters.ImageFilterSaturated;
36 import com.android.gallery3d.filtershow.filters.ImageFilterShadows;
37 import com.android.gallery3d.filtershow.filters.ImageFilterSharpen;
38 import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
39 import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
40 import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
41 import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
42 import com.android.gallery3d.filtershow.imageshow.ImageCrop;
43 import com.android.gallery3d.filtershow.imageshow.ImageShow;
44 import com.android.gallery3d.filtershow.presets.ImagePreset;
45 import com.android.gallery3d.filtershow.ui.FramedTextButton;
46 import com.android.gallery3d.filtershow.ui.ImageButtonTitle;
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 private int mCurrentAspectButton = 0;
142 private static final int NUMBER_OF_ASPECT_BUTTONS = 6;
143 private static final int ASPECT_NONE = 0;
144 private static final int ASPECT_1TO1 = 1;
145 private static final int ASPECT_5TO7 = 2;
146 private static final int ASPECT_4TO6 = 3;
147 private static final int ASPECT_16TO9 = 4;
148 private static final int ASPECT_ORIG = 5;
150 public UtilityPanel(Context context, View view, View textView,
151 View aspectButton, View curvesButton) {
154 mTextView = (TextView) textView;
155 mAspectButton = aspectButton;
156 mCurvesButton = curvesButton;
159 public boolean selected() {
163 public void setAspectButton(FramedTextButton button, int itemId) {
164 ImageCrop imageCrop = (ImageCrop) mCurrentImage;
166 case R.id.crop_menu_1to1: {
167 button.setText(mContext.getString(R.string.aspect1to1_effect));
168 imageCrop.apply(1, 1);
171 case R.id.crop_menu_4to6: {
172 button.setText(mContext.getString(R.string.aspect4to6_effect));
173 imageCrop.apply(6, 4);
176 case R.id.crop_menu_5to7: {
177 button.setText(mContext.getString(R.string.aspect5to7_effect));
178 imageCrop.apply(7, 5);
181 case R.id.crop_menu_9to16: {
182 button.setText(mContext.getString(R.string.aspect9to16_effect));
183 imageCrop.apply(16, 9);
186 case R.id.crop_menu_none: {
187 button.setText(mContext.getString(R.string.aspectNone_effect));
188 imageCrop.applyClear();
191 case R.id.crop_menu_original: {
192 button.setText(mContext.getString(R.string.aspectOriginal_effect));
193 imageCrop.applyOriginal();
197 imageCrop.invalidate();
200 public void nextAspectButton() {
201 if (mAspectButton instanceof ImageButtonTitle
202 && mCurrentImage instanceof ImageCrop) {
203 switch (mCurrentAspectButton) {
205 ((ImageButtonTitle) mAspectButton).setText(mContext
206 .getString(R.string.aspect)
208 + mContext.getString(R.string.aspect1to1_effect));
209 ((ImageCrop) mCurrentImage).apply(1, 1);
212 ((ImageButtonTitle) mAspectButton).setText(mContext
213 .getString(R.string.aspect)
215 + mContext.getString(R.string.aspect5to7_effect));
216 ((ImageCrop) mCurrentImage).apply(7, 5);
219 ((ImageButtonTitle) mAspectButton).setText(mContext
220 .getString(R.string.aspect)
222 + mContext.getString(R.string.aspect4to6_effect));
223 ((ImageCrop) mCurrentImage).apply(6, 4);
226 ((ImageButtonTitle) mAspectButton).setText(mContext
227 .getString(R.string.aspect)
229 + mContext.getString(R.string.aspect9to16_effect));
230 ((ImageCrop) mCurrentImage).apply(16, 9);
233 ((ImageButtonTitle) mAspectButton).setText(mContext
234 .getString(R.string.aspect)
236 + mContext.getString(R.string.aspectOriginal_effect));
237 ((ImageCrop) mCurrentImage).applyOriginal();
240 ((ImageButtonTitle) mAspectButton).setText(mContext
241 .getString(R.string.aspect)
243 + mContext.getString(R.string.aspectNone_effect));
244 ((ImageCrop) mCurrentImage).applyClear();
247 ((ImageButtonTitle) mAspectButton).setText(mContext
248 .getString(R.string.aspect)
250 + mContext.getString(R.string.aspectNone_effect));
251 ((ImageCrop) mCurrentImage).applyClear();
252 mCurrentAspectButton = ASPECT_NONE;
255 mCurrentAspectButton = (mCurrentAspectButton + 1) % NUMBER_OF_ASPECT_BUTTONS;
259 void setCurrentAspectButton(int n) {
260 mCurrentAspectButton = n;
263 public void showAspectButtons() {
264 if (mAspectButton != null)
265 mAspectButton.setVisibility(View.VISIBLE);
268 public void hideAspectButtons() {
269 if (mAspectButton != null)
270 mAspectButton.setVisibility(View.GONE);
273 public void showCurvesButtons() {
274 if (mCurvesButton != null)
275 mCurvesButton.setVisibility(View.VISIBLE);
278 public void hideCurvesButtons() {
279 if (mCurvesButton != null)
280 mCurvesButton.setVisibility(View.GONE);
283 public void onNewValue(int value) {
284 mParameterValue = value;
288 public void setEffectName(String effectName) {
289 mEffectName = effectName;
290 setShowParameter(true);
293 public void setShowParameter(boolean s) {
294 mShowParameterValue = s;
298 public void updateText() {
299 String apply = mContext.getString(R.string.apply_effect);
300 if (mShowParameterValue) {
301 mTextView.setText(Html.fromHtml(apply + " " + mEffectName + " "
304 mTextView.setText(Html.fromHtml(apply + " " + mEffectName));
308 public ViewPropertyAnimator unselect() {
309 ViewPropertyAnimator anim = mView.animate();
312 int h = mRowPanel.getHeight();
314 anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
317 mView.setVisibility(View.GONE);
324 public ViewPropertyAnimator select() {
325 mView.setVisibility(View.VISIBLE);
326 int h = mRowPanel.getHeight();
330 ViewPropertyAnimator anim = mView.animate();
332 anim.setDuration(ANIM_DURATION).withLayer();
339 private final int mType;
340 private final View mView;
342 public ViewType(View view, int type) {
352 private final HashMap<View, Panel> mPanels = new HashMap<View, Panel>();
353 private final HashMap<View, ViewType> mViews = new HashMap<View, ViewType>();
354 private final Vector<View> mImageViews = new Vector<View>();
355 private View mCurrentPanel = null;
356 private View mRowPanel = null;
357 private UtilityPanel mUtilityPanel = null;
358 private ImageShow mMasterImage = null;
359 private ImageShow mCurrentImage = null;
361 public void addView(View view) {
362 view.setOnClickListener(this);
363 mViews.put(view, new ViewType(view, COMPONENT));
366 public void addPanel(View view, View container, int position) {
367 mPanels.put(view, new Panel(view, container, position));
368 view.setOnClickListener(this);
369 mViews.put(view, new ViewType(view, PANEL));
372 public void addComponent(View aPanel, View component) {
373 Panel panel = mPanels.get(aPanel);
377 panel.addView(component);
378 component.setOnClickListener(this);
379 mViews.put(component, new ViewType(component, COMPONENT));
382 public void addImageView(View view) {
383 mImageViews.add(view);
384 ImageShow imageShow = (ImageShow) view;
385 imageShow.setPanelController(this);
388 public void resetParameters() {
389 showPanel(mCurrentPanel);
390 if (mCurrentImage != null) {
391 mCurrentImage.resetParameter();
392 mCurrentImage.select();
396 public boolean onBackPressed() {
397 if (mUtilityPanel == null || !mUtilityPanel.selected()) {
400 HistoryAdapter adapter = mMasterImage.getHistory();
401 int position = adapter.undo();
402 mMasterImage.onItemClick(position);
403 showPanel(mCurrentPanel);
404 mCurrentImage.select();
408 public void onNewValue(int value) {
409 mUtilityPanel.onNewValue(value);
412 public void showParameter(boolean s) {
413 mUtilityPanel.setShowParameter(s);
416 public void setCurrentPanel(View panel) {
420 public void setRowPanel(View rowPanel) {
421 mRowPanel = rowPanel;
424 public void setUtilityPanel(Context context, View utilityPanel, View textView,
425 View aspectButton, View curvesButton) {
426 mUtilityPanel = new UtilityPanel(context, utilityPanel, textView,
427 aspectButton, curvesButton);
430 public void setMasterImage(ImageShow imageShow) {
431 mMasterImage = imageShow;
435 public void onClick(View view) {
436 ViewType type = mViews.get(view);
437 if (type.type() == PANEL) {
439 } else if (type.type() == COMPONENT) {
444 public ImageShow showImageView(int id) {
445 ImageShow image = null;
446 for (View view : mImageViews) {
447 if (view.getId() == id) {
448 view.setVisibility(View.VISIBLE);
449 image = (ImageShow) view;
451 view.setVisibility(View.GONE);
457 public void showDefaultImageView() {
458 showImageView(R.id.imageShow).setShowControls(false);
459 mMasterImage.setCurrentFilter(null);
462 public void showPanel(View view) {
463 view.setVisibility(View.VISIBLE);
464 boolean removedUtilityPanel = false;
465 Panel current = mPanels.get(mCurrentPanel);
466 if (mUtilityPanel != null && mUtilityPanel.selected()) {
467 ViewPropertyAnimator anim1 = mUtilityPanel.unselect();
468 removedUtilityPanel = true;
470 if (mCurrentPanel == view) {
471 ViewPropertyAnimator anim2 = current.select(-1, VERTICAL_MOVE);
473 showDefaultImageView();
477 if (mCurrentPanel == view) {
481 Panel panel = mPanels.get(view);
482 if (!removedUtilityPanel) {
484 if (current != null) {
485 currentPos = current.getPosition();
487 ViewPropertyAnimator anim1 = panel.select(currentPos, HORIZONTAL_MOVE);
489 if (current != null) {
490 ViewPropertyAnimator anim2 = current.unselect(panel.getPosition(), HORIZONTAL_MOVE);
494 ViewPropertyAnimator anim = panel.select(-1, VERTICAL_MOVE);
497 showDefaultImageView();
498 mCurrentPanel = view;
501 public ImagePreset getImagePreset() {
502 return mMasterImage.getImagePreset();
505 public ImageFilter setImagePreset(ImageFilter filter, String name) {
506 ImagePreset copy = new ImagePreset(getImagePreset());
508 copy.setHistoryName(name);
510 mMasterImage.setImagePreset(copy);
514 public void ensureFilter(String name) {
515 ImagePreset preset = getImagePreset();
516 ImageFilter filter = preset.getFilter(name);
517 if (filter != null) {
518 // If we already have a filter, we might still want
519 // to push it onto the history stack.
520 ImagePreset copy = new ImagePreset(getImagePreset());
521 copy.setHistoryName(name);
522 mMasterImage.setImagePreset(copy);
523 filter = copy.getFilter(name);
526 if (filter == null && name.equalsIgnoreCase(
527 mCurrentImage.getContext().getString(R.string.curvesRGB))) {
528 filter = setImagePreset(new ImageFilterCurves(), name);
530 if (filter == null && name.equalsIgnoreCase(
531 mCurrentImage.getContext().getString(R.string.tinyplanet))) {
532 filter = setImagePreset(new ImageFilterTinyPlanet(), name);
535 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.vignette))) {
536 filter = setImagePreset(new ImageFilterVignette(), name);
539 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.sharpness))) {
540 filter = setImagePreset(new ImageFilterSharpen(), name);
543 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.contrast))) {
544 filter = setImagePreset(new ImageFilterContrast(), name);
547 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.saturation))) {
548 filter = setImagePreset(new ImageFilterSaturated(), name);
551 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.hue))) {
552 filter = setImagePreset(new ImageFilterHue(), name);
555 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.exposure))) {
556 filter = setImagePreset(new ImageFilterExposure(), name);
559 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.vibrance))) {
560 filter = setImagePreset(new ImageFilterVibrance(), name);
563 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(
564 R.string.shadow_recovery))) {
565 filter = setImagePreset(new ImageFilterShadows(), name);
568 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.redeye))) {
569 filter = setImagePreset(new ImageFilterRedEye(), name);
572 && name.equalsIgnoreCase(mCurrentImage.getContext().getString(R.string.wbalance))) {
573 filter = setImagePreset(new ImageFilterWBalance(), name);
575 mMasterImage.setCurrentFilter(filter);
578 private void showCurvesPopupMenu(final ImageCurves curves, final FramedTextButton anchor) {
579 PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
580 popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves, popupMenu.getMenu());
581 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
583 public boolean onMenuItemClick(MenuItem item) {
584 curves.setChannel(item.getItemId());
585 anchor.setTextFrom(item.getItemId());
592 private void showCropPopupMenu(final FramedTextButton anchor) {
593 PopupMenu popupMenu = new PopupMenu(mCurrentImage.getContext(), anchor);
594 popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_crop, popupMenu.getMenu());
595 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
597 public boolean onMenuItemClick(MenuItem item) {
598 mUtilityPanel.setAspectButton(anchor, item.getItemId());
605 public void showComponent(View view) {
606 if (mUtilityPanel != null && !mUtilityPanel.selected()) {
607 Panel current = mPanels.get(mCurrentPanel);
608 ViewPropertyAnimator anim1 = current.unselect(-1, VERTICAL_MOVE);
610 if (mUtilityPanel != null) {
611 ViewPropertyAnimator anim2 = mUtilityPanel.select();
616 if (view.getId() == R.id.pickCurvesChannel) {
617 ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
618 showCurvesPopupMenu(curves, (FramedTextButton) view);
622 if (view.getId() == R.id.aspect) {
623 showCropPopupMenu((FramedTextButton) view);
627 if (mCurrentImage != null) {
628 mCurrentImage.unselect();
630 mUtilityPanel.hideAspectButtons();
631 mUtilityPanel.hideCurvesButtons();
632 switch (view.getId()) {
633 case R.id.tinyplanetButton: {
634 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
635 String ename = mCurrentImage.getContext().getString(R.string.tinyplanet);
636 mUtilityPanel.setEffectName(ename);
640 case R.id.straightenButton: {
641 mCurrentImage = showImageView(R.id.imageStraighten);
642 String ename = mCurrentImage.getContext().getString(R.string.straighten);
643 mUtilityPanel.setEffectName(ename);
646 case R.id.cropButton: {
647 mCurrentImage = showImageView(R.id.imageCrop);
648 String ename = mCurrentImage.getContext().getString(R.string.crop);
649 mUtilityPanel.setEffectName(ename);
650 mUtilityPanel.setShowParameter(false);
651 mUtilityPanel.setCurrentAspectButton(-1);
652 mUtilityPanel.nextAspectButton();
653 mUtilityPanel.showAspectButtons();
656 case R.id.rotateButton: {
657 mCurrentImage = showImageView(R.id.imageRotate);
658 String ename = mCurrentImage.getContext().getString(R.string.rotate);
659 mUtilityPanel.setEffectName(ename);
662 case R.id.flipButton: {
663 mCurrentImage = showImageView(R.id.imageFlip);
664 String ename = mCurrentImage.getContext().getString(R.string.mirror);
665 mUtilityPanel.setEffectName(ename);
666 mUtilityPanel.setShowParameter(false);
669 case R.id.vignetteButton: {
670 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
671 String ename = mCurrentImage.getContext().getString(R.string.vignette);
672 mUtilityPanel.setEffectName(ename);
676 case R.id.curvesButtonRGB: {
677 ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
678 String ename = curves.getContext().getString(R.string.curvesRGB);
679 mUtilityPanel.setEffectName(ename);
680 mUtilityPanel.setShowParameter(false);
681 mUtilityPanel.showCurvesButtons();
682 mCurrentImage = curves;
686 case R.id.sharpenButton: {
687 mCurrentImage = showImageView(R.id.imageZoom).setShowControls(true);
688 String ename = mCurrentImage.getContext().getString(R.string.sharpness);
689 mUtilityPanel.setEffectName(ename);
693 case R.id.contrastButton: {
694 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
695 String ename = mCurrentImage.getContext().getString(R.string.contrast);
696 mUtilityPanel.setEffectName(ename);
700 case R.id.saturationButton: {
701 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
702 String ename = mCurrentImage.getContext().getString(R.string.saturation);
703 mUtilityPanel.setEffectName(ename);
707 case R.id.wbalanceButton: {
708 mCurrentImage = showImageView(R.id.imageShow).setShowControls(false);
709 String ename = mCurrentImage.getContext().getString(R.string.wbalance);
710 mUtilityPanel.setEffectName(ename);
711 mUtilityPanel.setShowParameter(false);
715 case R.id.hueButton: {
716 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
717 String ename = mCurrentImage.getContext().getString(R.string.hue);
718 mUtilityPanel.setEffectName(ename);
722 case R.id.exposureButton: {
723 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
724 String ename = mCurrentImage.getContext().getString(R.string.exposure);
725 mUtilityPanel.setEffectName(ename);
729 case R.id.vibranceButton: {
730 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
731 String ename = mCurrentImage.getContext().getString(R.string.vibrance);
732 mUtilityPanel.setEffectName(ename);
736 case R.id.shadowRecoveryButton: {
737 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
738 String ename = mCurrentImage.getContext().getString(R.string.shadow_recovery);
739 mUtilityPanel.setEffectName(ename);
743 case R.id.redEyeButton: {
744 mCurrentImage = showImageView(R.id.imageShow).setShowControls(true);
745 String ename = mCurrentImage.getContext().getString(R.string.redeye);
746 mUtilityPanel.setEffectName(ename);
751 mUtilityPanel.nextAspectButton();
752 mUtilityPanel.showAspectButtons();
755 case R.id.applyEffect: {
756 showPanel(mCurrentPanel);
760 mCurrentImage.select();