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.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;
51 import java.util.HashMap;
52 import java.util.Vector;
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;
63 public void setFixedAspect(boolean t) {
68 private final View mView;
69 private final View mContainer;
70 private int mPosition = 0;
71 private final Vector<View> mSubviews = new Vector<View>();
73 public Panel(View view, View container, int position) {
75 mContainer = container;
79 public void addView(View view) {
83 public int getPosition() {
87 public ViewPropertyAnimator unselect(int newPos, int move) {
88 ViewPropertyAnimator anim = mContainer.animate();
89 mView.setSelected(false);
93 int w = mRowPanel.getWidth();
94 int h = mRowPanel.getHeight();
95 if (move == HORIZONTAL_MOVE) {
96 if (newPos > mPosition) {
102 } else if (move == VERTICAL_MOVE) {
105 anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
108 mContainer.setVisibility(View.GONE);
114 public ViewPropertyAnimator select(int oldPos, int move) {
115 mView.setSelected(true);
116 mContainer.setVisibility(View.VISIBLE);
119 ViewPropertyAnimator anim = mContainer.animate();
120 int w = mRowPanel.getWidth();
121 int h = mRowPanel.getHeight();
122 if (move == HORIZONTAL_MOVE) {
123 if (oldPos < mPosition) {
129 } else if (move == VERTICAL_MOVE) {
133 anim.setDuration(ANIM_DURATION).withLayer();
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;
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 String t = mContext.getString(R.string.aspect1to1_effect);
169 imageCrop.apply(1, 1);
170 imageCrop.setAspectString(t);
173 case R.id.crop_menu_4to3: {
174 String t = mContext.getString(R.string.aspect4to3_effect);
176 imageCrop.apply(4, 3);
177 imageCrop.setAspectString(t);
180 case R.id.crop_menu_3to4: {
181 String t = mContext.getString(R.string.aspect3to4_effect);
183 imageCrop.apply(3, 4);
184 imageCrop.setAspectString(t);
187 case R.id.crop_menu_5to7: {
188 String t = mContext.getString(R.string.aspect5to7_effect);
190 imageCrop.apply(5, 7);
191 imageCrop.setAspectString(t);
194 case R.id.crop_menu_7to5: {
195 String t = mContext.getString(R.string.aspect7to5_effect);
197 imageCrop.apply(7, 5);
198 imageCrop.setAspectString(t);
201 case R.id.crop_menu_none: {
202 String t = mContext.getString(R.string.aspectNone_effect);
204 imageCrop.applyClear();
205 imageCrop.setAspectString(t);
208 case R.id.crop_menu_original: {
209 String t = mContext.getString(R.string.aspectOriginal_effect);
211 imageCrop.applyOriginal();
212 imageCrop.setAspectString(t);
216 imageCrop.invalidate();
219 public void showAspectButtons() {
220 if (mAspectButton != null)
221 mAspectButton.setVisibility(View.VISIBLE);
224 public void hideAspectButtons() {
225 if (mAspectButton != null)
226 mAspectButton.setVisibility(View.GONE);
229 public void showCurvesButtons() {
230 if (mCurvesButton != null)
231 mCurvesButton.setVisibility(View.VISIBLE);
234 public void hideCurvesButtons() {
235 if (mCurvesButton != null)
236 mCurvesButton.setVisibility(View.GONE);
239 public void onNewValue(int value) {
240 mParameterValue = value;
244 public void setEffectName(String effectName) {
245 mEffectName = effectName;
246 setShowParameter(true);
249 public void setShowParameter(boolean s) {
250 mShowParameterValue = s;
254 public void updateText() {
255 String apply = mContext.getString(R.string.apply_effect);
256 if (mShowParameterValue) {
257 mTextView.setText(Html.fromHtml(apply + " " + mEffectName + " "
260 mTextView.setText(Html.fromHtml(apply + " " + mEffectName));
264 public ViewPropertyAnimator unselect() {
265 ViewPropertyAnimator anim = mView.animate();
268 int h = mRowPanel.getHeight();
270 anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
273 mView.setVisibility(View.GONE);
280 public ViewPropertyAnimator select() {
281 mView.setVisibility(View.VISIBLE);
282 int h = mRowPanel.getHeight();
286 ViewPropertyAnimator anim = mView.animate();
288 anim.setDuration(ANIM_DURATION).withLayer();
295 private final int mType;
296 private final View mView;
298 public ViewType(View view, int type) {
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;
319 public void setActivity(FilterShowActivity activity) {
320 mActivity = activity;
323 public void addView(View view) {
324 view.setOnClickListener(this);
325 mViews.put(view, new ViewType(view, COMPONENT));
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));
334 public void addComponent(View aPanel, View component) {
335 Panel panel = mPanels.get(aPanel);
339 panel.addView(component);
340 component.setOnClickListener(this);
341 mViews.put(component, new ViewType(component, COMPONENT));
344 public void addFilter(ImageFilter filter) {
345 mFilters.put(filter.getName(), filter);
348 public void addImageView(View view) {
349 mImageViews.add(view);
350 ImageShow imageShow = (ImageShow) view;
351 imageShow.setPanelController(this);
354 public void resetParameters() {
355 showPanel(mCurrentPanel);
356 if (mCurrentImage != null) {
357 mCurrentImage.resetParameter();
358 mCurrentImage.select();
362 public boolean onBackPressed() {
363 if (mUtilityPanel == null || !mUtilityPanel.selected()) {
366 HistoryAdapter adapter = mMasterImage.getHistory();
367 int position = adapter.undo();
368 mMasterImage.onItemClick(position);
369 showPanel(mCurrentPanel);
370 mCurrentImage.select();
374 public void onNewValue(int value) {
375 mUtilityPanel.onNewValue(value);
378 public void showParameter(boolean s) {
379 mUtilityPanel.setShowParameter(s);
382 public void setCurrentPanel(View panel) {
386 public void setRowPanel(View rowPanel) {
387 mRowPanel = rowPanel;
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);
396 public void setMasterImage(ImageShow imageShow) {
397 mMasterImage = imageShow;
401 public void onClick(View view) {
402 ViewType type = mViews.get(view);
403 if (type.type() == PANEL) {
405 } else if (type.type() == COMPONENT) {
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;
417 view.setVisibility(View.GONE);
423 public void showDefaultImageView() {
424 showImageView(R.id.imageShow).setShowControls(false);
425 mMasterImage.setCurrentFilter(null);
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;
436 if (mCurrentPanel == view) {
437 ViewPropertyAnimator anim2 = current.select(-1, VERTICAL_MOVE);
439 showDefaultImageView();
443 if (mCurrentPanel == view) {
447 Panel panel = mPanels.get(view);
448 if (!removedUtilityPanel) {
450 if (current != null) {
451 currentPos = current.getPosition();
453 ViewPropertyAnimator anim1 = panel.select(currentPos, HORIZONTAL_MOVE);
455 if (current != null) {
456 ViewPropertyAnimator anim2 = current.unselect(panel.getPosition(), HORIZONTAL_MOVE);
460 ViewPropertyAnimator anim = panel.select(-1, VERTICAL_MOVE);
463 showDefaultImageView();
464 mCurrentPanel = view;
467 public ImagePreset getImagePreset() {
468 return mMasterImage.getImagePreset();
471 public ImageFilter setImagePreset(ImageFilter filter, String name) {
472 ImagePreset copy = new ImagePreset(getImagePreset());
474 copy.setHistoryName(name);
476 mMasterImage.setImagePreset(copy);
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);
492 if (filter == null) {
493 ImageFilter filterInstance = mFilters.get(name);
494 if (filterInstance != null) {
496 ImageFilter newFilter = filterInstance.clone();
498 filter = setImagePreset(newFilter, name);
499 } catch (CloneNotSupportedException e) {
504 if (filter != null) {
505 mMasterImage.setCurrentFilter(filter);
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() {
514 public boolean onMenuItemClick(MenuItem item) {
515 curves.setChannel(item.getItemId());
516 anchor.setTextFrom(item.getItemId());
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() {
528 public boolean onMenuItemClick(MenuItem item) {
529 mUtilityPanel.setAspectButton(anchor, item.getItemId());
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);
541 if (mUtilityPanel != null) {
542 ViewPropertyAnimator anim2 = mUtilityPanel.select();
547 if (view.getId() == R.id.pickCurvesChannel) {
548 ImageCurves curves = (ImageCurves) showImageView(R.id.imageCurves);
549 showCurvesPopupMenu(curves, (FramedTextButton) view);
553 if (view.getId() == R.id.aspect) {
554 showCropPopupMenu((FramedTextButton) view);
558 if (mCurrentImage != null) {
559 mCurrentImage.unselect();
561 mUtilityPanel.hideAspectButtons();
562 mUtilityPanel.hideCurvesButtons();
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();
577 mUtilityPanel.setShowParameter(filter.showParameterValue());
579 mCurrentImage.select();
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);
592 case R.id.straightenButton: {
593 mCurrentImage = showImageView(R.id.imageStraighten);
594 String ename = mCurrentImage.getContext().getString(R.string.straighten);
595 mUtilityPanel.setEffectName(ename);
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;
608 mUtilityPanel.showAspectButtons();
612 case R.id.rotateButton: {
613 mCurrentImage = showImageView(R.id.imageRotate);
614 String ename = mCurrentImage.getContext().getString(R.string.rotate);
615 mUtilityPanel.setEffectName(ename);
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);
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);
633 mUtilityPanel.showAspectButtons();
636 case R.id.applyEffect: {
637 if (mMasterImage.getCurrentFilter() instanceof ImageFilterTinyPlanet) {
638 mActivity.saveImage();
640 if (mCurrentImage instanceof ImageCrop) {
641 ((ImageCrop) mCurrentImage).saveAndSetPreset();
643 showPanel(mCurrentPanel);
648 mCurrentImage.select();