Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.gallery3d.photoeditor; |
| 18 | |
| 19 | import android.content.Context; |
| 20 | import android.util.AttributeSet; |
| 21 | import android.view.LayoutInflater; |
| 22 | import android.view.View; |
| 23 | import android.view.ViewGroup; |
| 24 | import android.widget.LinearLayout; |
| 25 | import android.widget.TextView; |
| 26 | |
| 27 | import com.android.gallery3d.R; |
| 28 | import com.android.gallery3d.photoeditor.actions.EffectAction; |
| 29 | import com.android.gallery3d.photoeditor.actions.EffectToolFactory; |
| 30 | |
| 31 | /** |
| 32 | * Effects bar that contains all effects and shows them in categorized views. |
| 33 | */ |
| 34 | public class EffectsBar extends LinearLayout { |
| 35 | |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 36 | private final LayoutInflater inflater; |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 37 | private FilterStack filterStack; |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 38 | private EffectsMenu effectsMenu; |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 39 | private View effectsGallery; |
| 40 | private ViewGroup effectToolPanel; |
| 41 | private EffectAction activeEffect; |
| 42 | |
| 43 | public EffectsBar(Context context, AttributeSet attrs) { |
| 44 | super(context, attrs); |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 45 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | public void initialize(FilterStack filterStack) { |
| 49 | this.filterStack = filterStack; |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 50 | |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 51 | 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 Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 70 | } |
| 71 | |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 72 | 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 Ruesga | a901f88 | 2012-06-12 23:28:58 +0200 | [diff] [blame^] | 77 | 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 Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 84 | } |
| 85 | scrollView.addView(effects); |
| 86 | scrollView.scrollTo(0, 0); |
| 87 | addView(effectsGallery, 0); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 88 | } |
| 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 Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 101 | activeEffect.begin(filterStack, |
| 102 | new EffectToolFactory(effectToolPanel, inflater)); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 103 | } |
| 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 Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 120 | private boolean exitEffectsGallery() { |
| 121 | if (effectsGallery != null) { |
| 122 | if (activeEffect != null) { |
Yuli Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 123 | // Detach the active effect to prevent it stopping effects-gallery from gc. |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 124 | 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 Huang | 3235a3e | 2011-11-14 22:38:16 +0800 | [diff] [blame] | 136 | SpinnerProgressDialog.showDialog(); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 137 | activeEffect.end(new Runnable() { |
| 138 | |
| 139 | @Override |
| 140 | public void run() { |
Yuli Huang | 3235a3e | 2011-11-14 22:38:16 +0800 | [diff] [blame] | 141 | SpinnerProgressDialog.dismissDialog(); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 142 | 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 Huang | b5c54b6 | 2011-10-18 12:42:50 +0800 | [diff] [blame] | 166 | effectsMenu.clearSelected(); |
Yuli Huang | 6a12ad7 | 2011-09-12 22:25:30 +0800 | [diff] [blame] | 167 | |
| 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 | } |