blob: 1510c2f010108a7d5ac3f8a29485c6bb4628ee82 [file] [log] [blame]
Yuli Huang6a12ad72011-09-12 22:25:30 +08001/*
2 * Copyright (C) 2010 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
17package com.android.gallery3d.photoeditor;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.view.LayoutInflater;
22import android.view.View;
23import android.view.ViewGroup;
24import android.widget.LinearLayout;
25import android.widget.TextView;
26
27import com.android.gallery3d.R;
28import com.android.gallery3d.photoeditor.actions.EffectAction;
29import com.android.gallery3d.photoeditor.actions.EffectToolFactory;
30
31/**
32 * Effects bar that contains all effects and shows them in categorized views.
33 */
34public class EffectsBar extends LinearLayout {
35
Yuli Huangb5c54b62011-10-18 12:42:50 +080036 private final LayoutInflater inflater;
Yuli Huang6a12ad72011-09-12 22:25:30 +080037 private FilterStack filterStack;
Yuli Huangb5c54b62011-10-18 12:42:50 +080038 private EffectsMenu effectsMenu;
Yuli Huang6a12ad72011-09-12 22:25:30 +080039 private View effectsGallery;
40 private ViewGroup effectToolPanel;
41 private EffectAction activeEffect;
42
43 public EffectsBar(Context context, AttributeSet attrs) {
44 super(context, attrs);
Yuli Huangb5c54b62011-10-18 12:42:50 +080045 inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Yuli Huang6a12ad72011-09-12 22:25:30 +080046 }
47
48 public void initialize(FilterStack filterStack) {
49 this.filterStack = filterStack;
Yuli Huang6a12ad72011-09-12 22:25:30 +080050
Yuli Huangb5c54b62011-10-18 12:42:50 +080051 effectsMenu = (EffectsMenu) findViewById(R.id.effects_menu);
52 effectsMenu.setOnToggleListener(new EffectsMenu.OnToggleListener() {
53
54 @Override
55 public boolean onToggle(boolean isSelected, final int effectsId) {
56 // Create and show effects-gallery only if the clicked toggle isn't selected or it's
57 // selected but showing an active effect instead of effects-gallery. Set the clicked
58 // toggle selected only when its effects-gallery will be created and shown.
59 boolean select = !isSelected || (effectsGallery == null);
60 exit(select ? new Runnable() {
61
62 @Override
63 public void run() {
64 createEffectsGallery(effectsId);
65 }
66 } : null);
67 return select;
68 }
69 });
Yuli Huang6a12ad72011-09-12 22:25:30 +080070 }
71
Yuli Huangb5c54b62011-10-18 12:42:50 +080072 private void createEffectsGallery(int effectsId) {
73 // Inflate scrollable effects-gallery and desired effects into effects-bar.
74 effectsGallery = inflater.inflate(R.layout.photoeditor_effects_gallery, this, false);
75 ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
76 ViewGroup effects = (ViewGroup) inflater.inflate(effectsId, scrollView, false);
Jorge Ruesgaa901f882012-06-12 23:28:58 +020077 for (int i = effects.getChildCount()-1; i >= 0; i--) {
78 EffectAction effect = (EffectAction) effects.getChildAt(i);
79 if( !effect.isPresent() ){
80 effects.removeViewAt(i);
81 continue;
82 }
83 setupEffectListener(effect);
Yuli Huangb5c54b62011-10-18 12:42:50 +080084 }
85 scrollView.addView(effects);
86 scrollView.scrollTo(0, 0);
87 addView(effectsGallery, 0);
Yuli Huang6a12ad72011-09-12 22:25:30 +080088 }
89
90 private void setupEffectListener(final EffectAction effect) {
91 effect.setListener(new EffectAction.Listener() {
92
93 @Override
94 public void onClick() {
95 if (isEnabled()) {
96 // Set the clicked effect active before exiting effects-gallery.
97 activeEffect = effect;
98 exitEffectsGallery();
99 // Create effect tool panel first before the factory could create tools within.
100 createEffectToolPanel();
Yuli Huangb5c54b62011-10-18 12:42:50 +0800101 activeEffect.begin(filterStack,
102 new EffectToolFactory(effectToolPanel, inflater));
Yuli Huang6a12ad72011-09-12 22:25:30 +0800103 }
104 }
105
106 @Override
107 public void onDone() {
108 exit(null);
109 }
110 });
111 }
112
113 private void createEffectToolPanel() {
114 effectToolPanel = (ViewGroup) inflater.inflate(
115 R.layout.photoeditor_effect_tool_panel, this, false);
116 ((TextView) effectToolPanel.findViewById(R.id.effect_label)).setText(activeEffect.name());
117 addView(effectToolPanel, 0);
118 }
119
Yuli Huang6a12ad72011-09-12 22:25:30 +0800120 private boolean exitEffectsGallery() {
121 if (effectsGallery != null) {
122 if (activeEffect != null) {
Yuli Huangb5c54b62011-10-18 12:42:50 +0800123 // Detach the active effect to prevent it stopping effects-gallery from gc.
Yuli Huang6a12ad72011-09-12 22:25:30 +0800124 ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
125 ((ViewGroup) scrollView.getChildAt(0)).removeView(activeEffect);
126 }
127 removeView(effectsGallery);
128 effectsGallery = null;
129 return true;
130 }
131 return false;
132 }
133
134 private boolean exitActiveEffect(final Runnable runnableOnDone) {
135 if (activeEffect != null) {
Yuli Huang3235a3e2011-11-14 22:38:16 +0800136 SpinnerProgressDialog.showDialog();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800137 activeEffect.end(new Runnable() {
138
139 @Override
140 public void run() {
Yuli Huang3235a3e2011-11-14 22:38:16 +0800141 SpinnerProgressDialog.dismissDialog();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800142 View fullscreenTool = getRootView().findViewById(R.id.fullscreen_effect_tool);
143 if (fullscreenTool != null) {
144 ((ViewGroup) fullscreenTool.getParent()).removeView(fullscreenTool);
145 }
146 removeView(effectToolPanel);
147 effectToolPanel = null;
148 activeEffect = null;
149 if (runnableOnDone != null) {
150 runnableOnDone.run();
151 }
152 }
153 });
154 return true;
155 }
156 return false;
157 }
158
159 /**
160 * Exits from effects gallery or the active effect; then executes the runnable if applicable.
161 *
162 * @return true if exiting from effects gallery or the active effect; otherwise, false.
163 */
164 public boolean exit(final Runnable runnableOnDone) {
165 // Exit effects-menu selected states.
Yuli Huangb5c54b62011-10-18 12:42:50 +0800166 effectsMenu.clearSelected();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800167
168 if (exitActiveEffect(runnableOnDone)) {
169 return true;
170 }
171
172 boolean exited = exitEffectsGallery();
173 if (runnableOnDone != null) {
174 runnableOnDone.run();
175 }
176 return exited;
177 }
178}