summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/photoeditor
diff options
context:
space:
mode:
authorYuli Huang <yuli@google.com>2011-10-18 12:42:50 +0800
committerYuli Huang <yuli@google.com>2011-10-18 13:10:10 +0800
commit306f9d2b11f65e8ff35ad707a0d85c66c34b0c8b (patch)
tree7f5ab57c7144871ce1a73b6a36bb18dbc9f9de49 /src/com/android/gallery3d/photoeditor
parent903bb336e915b6c7ce560dd8a2c2722ae5fa3bf5 (diff)
downloadandroid_packages_apps_Snap-306f9d2b11f65e8ff35ad707a0d85c66c34b0c8b.tar.gz
android_packages_apps_Snap-306f9d2b11f65e8ff35ad707a0d85c66c34b0c8b.tar.bz2
android_packages_apps_Snap-306f9d2b11f65e8ff35ad707a0d85c66c34b0c8b.zip
Fix b/5403449.
1. Extract code that recreates/restores ActionBar as RestorableView, and make both ActionBar and EffectsMenu extend RestorableView. 2. Fix effects-menu buttons too close to each other. 3. Remove effects-menu buttons' highlight animations to look more responsive. Change-Id: I68e5bdcde702e611ccced5e169852c0e58a949fc
Diffstat (limited to 'src/com/android/gallery3d/photoeditor')
-rw-r--r--src/com/android/gallery3d/photoeditor/ActionBar.java99
-rw-r--r--src/com/android/gallery3d/photoeditor/EffectsBar.java76
-rw-r--r--src/com/android/gallery3d/photoeditor/EffectsMenu.java81
-rw-r--r--src/com/android/gallery3d/photoeditor/PhotoEditor.java46
-rw-r--r--src/com/android/gallery3d/photoeditor/RestorableView.java107
5 files changed, 270 insertions, 139 deletions
diff --git a/src/com/android/gallery3d/photoeditor/ActionBar.java b/src/com/android/gallery3d/photoeditor/ActionBar.java
index db18c7454..814ee8ecb 100644
--- a/src/com/android/gallery3d/photoeditor/ActionBar.java
+++ b/src/com/android/gallery3d/photoeditor/ActionBar.java
@@ -17,33 +17,27 @@
package com.android.gallery3d.photoeditor;
import android.content.Context;
+import android.content.res.Configuration;
import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RelativeLayout;
import android.widget.ViewSwitcher;
import com.android.gallery3d.R;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map.Entry;
-
/**
* Action bar that contains buttons such as undo, redo, save, etc.
*/
-public class ActionBar extends RelativeLayout {
-
- private static final float ENABLED_ALPHA = 1;
- private static final float DISABLED_ALPHA = 0.47f;
-
- private final HashMap<Integer, Runnable> buttonRunnables = new HashMap<Integer, Runnable>();
- private final HashSet<Integer> changedButtons = new HashSet<Integer>();
+public class ActionBar extends RestorableView {
public ActionBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
+ protected int childLayoutId() {
+ return R.layout.photoeditor_actionbar;
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@@ -58,66 +52,51 @@ public class ActionBar extends RelativeLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ updateButtons(false, false);
+ }
- enableButton(R.id.undo_button, false);
- enableButton(R.id.redo_button, false);
- enableButton(R.id.save_button, false);
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ showSaveOrShare();
}
/**
- * Restores the passed action-bar.
- *
- * @return the passed parameter.
+ * Save/share button may need being switched when undo/save enabled status is changed/restored.
*/
- public ActionBar restore(ActionBar actionBar) {
- // Restores by runnables and enabled status of buttons that have been changed.
- for (Entry<Integer, Runnable> entry : buttonRunnables.entrySet()) {
- actionBar.setRunnable(entry.getKey(), entry.getValue());
- }
- for (int buttonId : changedButtons) {
- actionBar.enableButton(buttonId, isButtonEnabled(buttonId));
+ private void showSaveOrShare() {
+ // Show share-button only after photo is edited and saved; otherwise, show save-button.
+ boolean showShare = findViewById(R.id.undo_button).isEnabled()
+ && !findViewById(R.id.save_button).isEnabled();
+ ViewSwitcher switcher = (ViewSwitcher) findViewById(R.id.save_share_buttons);
+ int next = switcher.getNextView().getId();
+ if ((showShare && (next == R.id.share_button))
+ || (!showShare && (next == R.id.save_button))) {
+ switcher.showNext();
}
- return actionBar;
}
- public void setRunnable(int buttonId, final Runnable r) {
- findViewById(buttonId).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (isEnabled()) {
- r.run();
- }
- }
- });
- buttonRunnables.put(buttonId, r);
+ public void updateButtons(boolean canUndo, boolean canRedo) {
+ setViewEnabled(R.id.undo_button, canUndo);
+ setViewEnabled(R.id.redo_button, canRedo);
+ setViewEnabled(R.id.save_button, canUndo);
+ showSaveOrShare();
}
- public void clickButton(int buttonId) {
- findViewById(buttonId).performClick();
+ public void updateSave(boolean canSave) {
+ setViewEnabled(R.id.save_button, canSave);
+ showSaveOrShare();
}
- public boolean isButtonEnabled(int buttonId) {
- return findViewById(buttonId).isEnabled();
+ public void clickBack() {
+ findViewById(R.id.action_bar_back).performClick();
}
- public void enableButton(int buttonId, boolean enabled) {
- View button = findViewById(buttonId);
- button.setEnabled(enabled);
- button.setAlpha(enabled ? ENABLED_ALPHA : DISABLED_ALPHA);
- // Track buttons whose enabled status has been updated.
- changedButtons.add(buttonId);
-
- if (buttonId == R.id.save_button) {
- // Show share-button only after photo is edited and saved; otherwise, show save-button.
- // TODO: Fix the assumption of undo enabled status must be updated before reaching here.
- boolean showShare = findViewById(R.id.undo_button).isEnabled() && !enabled;
- ViewSwitcher switcher = (ViewSwitcher) findViewById(R.id.save_share_buttons);
- int next = switcher.getNextView().getId();
- if ((showShare && (next == R.id.share_button))
- || (!showShare && (next == R.id.save_button))) {
- switcher.showNext();
- }
- }
+ public void clickSave() {
+ findViewById(R.id.save_button).performClick();
+ }
+
+ public boolean canSave() {
+ return findViewById(R.id.save_button).isEnabled();
}
}
diff --git a/src/com/android/gallery3d/photoeditor/EffectsBar.java b/src/com/android/gallery3d/photoeditor/EffectsBar.java
index 6e3178e1a..acb22b6e6 100644
--- a/src/com/android/gallery3d/photoeditor/EffectsBar.java
+++ b/src/com/android/gallery3d/photoeditor/EffectsBar.java
@@ -33,46 +33,55 @@ import com.android.gallery3d.photoeditor.actions.EffectToolFactory;
*/
public class EffectsBar extends LinearLayout {
+ private final LayoutInflater inflater;
private FilterStack filterStack;
- private LayoutInflater inflater;
+ private EffectsMenu effectsMenu;
private View effectsGallery;
private ViewGroup effectToolPanel;
private EffectAction activeEffect;
public EffectsBar(Context context, AttributeSet attrs) {
super(context, attrs);
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void initialize(FilterStack filterStack) {
this.filterStack = filterStack;
- inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- setupMenuToggle(R.id.exposure_button, R.layout.photoeditor_effects_exposure);
- setupMenuToggle(R.id.artistic_button, R.layout.photoeditor_effects_artistic);
- setupMenuToggle(R.id.color_button, R.layout.photoeditor_effects_color);
- setupMenuToggle(R.id.fix_button, R.layout.photoeditor_effects_fix);
-
- setEnabled(false);
- }
-
- private void setupMenuToggle(int toggleId, final int effectsId) {
- final View toggle = findViewById(toggleId);
- toggle.setOnClickListener(new View.OnClickListener() {
+ effectsMenu = (EffectsMenu) findViewById(R.id.effects_menu);
+ effectsMenu.setOnToggleListener(new EffectsMenu.OnToggleListener() {
@Override
- public void onClick(View v) {
- // Toggle off to exit effects gallery that is showing. Or toggle on to show effects
- // gallery after exiting an active effect if applicable.
- exit((toggle.isSelected() && (effectsGallery != null)) ? null : new Runnable() {
+ public boolean onToggle(boolean isSelected, final int effectsId) {
+ // Create and show effects-gallery only if the clicked toggle isn't selected or it's
+ // selected but showing an active effect instead of effects-gallery. Set the clicked
+ // toggle selected only when its effects-gallery will be created and shown.
+ boolean select = !isSelected || (effectsGallery == null);
+ exit(select ? new Runnable() {
@Override
public void run() {
- toggle.setSelected(true);
- showEffectsGallery(effectsId);
+ createEffectsGallery(effectsId);
}
- });
+ } : null);
+ return select;
}
});
+
+ setEnabled(false);
+ }
+
+ private void createEffectsGallery(int effectsId) {
+ // Inflate scrollable effects-gallery and desired effects into effects-bar.
+ effectsGallery = inflater.inflate(R.layout.photoeditor_effects_gallery, this, false);
+ ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
+ ViewGroup effects = (ViewGroup) inflater.inflate(effectsId, scrollView, false);
+ for (int i = 0; i < effects.getChildCount(); i++) {
+ setupEffectListener((EffectAction) effects.getChildAt(i));
+ }
+ scrollView.addView(effects);
+ scrollView.scrollTo(0, 0);
+ addView(effectsGallery, 0);
}
private void setupEffectListener(final EffectAction effect) {
@@ -86,8 +95,8 @@ public class EffectsBar extends LinearLayout {
exitEffectsGallery();
// Create effect tool panel first before the factory could create tools within.
createEffectToolPanel();
- activeEffect.begin(
- filterStack, new EffectToolFactory(effectToolPanel, inflater));
+ activeEffect.begin(filterStack,
+ new EffectToolFactory(effectToolPanel, inflater));
}
}
@@ -105,23 +114,10 @@ public class EffectsBar extends LinearLayout {
addView(effectToolPanel, 0);
}
- private void showEffectsGallery(int effectsId) {
- // Inflate scrollable effects-gallery and desired effects into effects-bar.
- effectsGallery = inflater.inflate(R.layout.photoeditor_effects_gallery, this, false);
- ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
- ViewGroup effects = (ViewGroup) inflater.inflate(effectsId, scrollView, false);
- for (int i = 0; i < effects.getChildCount(); i++) {
- setupEffectListener((EffectAction) effects.getChildAt(i));
- }
- scrollView.addView(effects);
- scrollView.scrollTo(0, 0);
- addView(effectsGallery, 0);
- }
-
private boolean exitEffectsGallery() {
if (effectsGallery != null) {
if (activeEffect != null) {
- // Detach the active effect from effects-gallery that could be recycled by gc.
+ // Detach the active effect to prevent it stopping effects-gallery from gc.
ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
((ViewGroup) scrollView.getChildAt(0)).removeView(activeEffect);
}
@@ -165,13 +161,7 @@ public class EffectsBar extends LinearLayout {
*/
public boolean exit(final Runnable runnableOnDone) {
// Exit effects-menu selected states.
- ViewGroup menu = (ViewGroup) findViewById(R.id.effects_menu);
- for (int i = 0; i < menu.getChildCount(); i++) {
- View toggle = menu.getChildAt(i);
- if (toggle.isSelected()) {
- toggle.setSelected(false);
- }
- }
+ effectsMenu.clearSelected();
if (exitActiveEffect(runnableOnDone)) {
return true;
diff --git a/src/com/android/gallery3d/photoeditor/EffectsMenu.java b/src/com/android/gallery3d/photoeditor/EffectsMenu.java
new file mode 100644
index 000000000..71614b105
--- /dev/null
+++ b/src/com/android/gallery3d/photoeditor/EffectsMenu.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.photoeditor;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.gallery3d.R;
+
+/**
+ * Effects menu that contains toggles mapping to corresponding groups of effects.
+ */
+public class EffectsMenu extends RestorableView {
+
+ /**
+ * Listener of toggle changes.
+ */
+ public interface OnToggleListener {
+
+ /**
+ * Listens to the selected status and mapped effects-id of the clicked toggle.
+ *
+ * @return true to make the toggle selected; otherwise, make it unselected.
+ */
+ boolean onToggle(boolean isSelected, int effectsId);
+ }
+
+ public EffectsMenu(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected int childLayoutId() {
+ return R.layout.photoeditor_effects_menu;
+ }
+
+ public void setOnToggleListener(OnToggleListener listener) {
+ setToggleRunnalbe(listener, R.id.exposure_button, R.layout.photoeditor_effects_exposure);
+ setToggleRunnalbe(listener, R.id.artistic_button, R.layout.photoeditor_effects_artistic);
+ setToggleRunnalbe(listener, R.id.color_button, R.layout.photoeditor_effects_color);
+ setToggleRunnalbe(listener, R.id.fix_button, R.layout.photoeditor_effects_fix);
+ }
+
+ private void setToggleRunnalbe(final OnToggleListener listener, final int toggleId,
+ final int effectsId) {
+ setClickRunnable(toggleId, new Runnable() {
+
+ @Override
+ public void run() {
+ boolean selected = findViewById(toggleId).isSelected();
+ setViewSelected(toggleId, listener.onToggle(selected, effectsId));
+ }
+ });
+ }
+
+ public void clearSelected() {
+ ViewGroup menu = (ViewGroup) findViewById(R.id.toggles);
+ for (int i = 0; i < menu.getChildCount(); i++) {
+ View toggle = menu.getChildAt(i);
+ if (toggle.isSelected()) {
+ setViewSelected(toggle.getId(), false);
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/photoeditor/PhotoEditor.java b/src/com/android/gallery3d/photoeditor/PhotoEditor.java
index 3a6face68..2294d0316 100644
--- a/src/com/android/gallery3d/photoeditor/PhotoEditor.java
+++ b/src/com/android/gallery3d/photoeditor/PhotoEditor.java
@@ -18,12 +18,9 @@ package com.android.gallery3d.photoeditor;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewGroup;
import com.android.gallery3d.R;
@@ -54,41 +51,18 @@ public class PhotoEditor extends Activity {
@Override
public void onStackChanged(boolean canUndo, boolean canRedo) {
- actionBar.enableButton(R.id.undo_button, canUndo);
- actionBar.enableButton(R.id.redo_button, canRedo);
- actionBar.enableButton(R.id.save_button, canUndo);
+ actionBar.updateButtons(canUndo, canRedo);
}
});
EffectsBar effectsBar = (EffectsBar) findViewById(R.id.effects_bar);
effectsBar.initialize(filterStack);
- actionBar.setRunnable(R.id.undo_button, createUndoRedoRunnable(true, effectsBar));
- actionBar.setRunnable(R.id.redo_button, createUndoRedoRunnable(false, effectsBar));
- actionBar.setRunnable(R.id.save_button, createSaveRunnable(effectsBar));
- actionBar.setRunnable(R.id.share_button, createShareRunnable(effectsBar));
- actionBar.setRunnable(R.id.action_bar_back, createBackRunnable(effectsBar));
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
- actionBar = actionBar.restore((ActionBar) recreateView(
- actionBar, inflater, R.layout.photoeditor_actionbar));
- }
-
- /**
- * Recreates the view by inflating the given layout id.
- */
- private View recreateView(View view, LayoutInflater inflater, int layoutId) {
- ViewGroup parent = (ViewGroup) view.getParent();
- int index = parent.indexOfChild(view);
- parent.removeViewAt(index);
-
- View recreated = inflater.inflate(layoutId, parent, false);
- parent.addView(recreated, index);
- return recreated;
+ actionBar.setClickRunnable(R.id.undo_button, createUndoRedoRunnable(true, effectsBar));
+ actionBar.setClickRunnable(R.id.redo_button, createUndoRedoRunnable(false, effectsBar));
+ actionBar.setClickRunnable(R.id.save_button, createSaveRunnable(effectsBar));
+ actionBar.setClickRunnable(R.id.share_button, createShareRunnable(effectsBar));
+ actionBar.setClickRunnable(R.id.action_bar_back, createBackRunnable(effectsBar));
}
private SpinnerProgressDialog createProgressDialog() {
@@ -160,7 +134,7 @@ public class PhotoEditor extends Activity {
@Override
public void onComplete(Uri result) {
progressDialog.dismiss();
- actionBar.enableButton(R.id.save_button, (result == null));
+ actionBar.updateSave(result == null);
saveUri = result;
}
};
@@ -203,12 +177,12 @@ public class PhotoEditor extends Activity {
// Exit effects or go back to the previous activity on pressing back button.
if (!effectsBar.exit(null)) {
// Pop-up a dialog to save unsaved photo.
- if (actionBar.isButtonEnabled(R.id.save_button)) {
+ if (actionBar.canSave()) {
new YesNoCancelDialogBuilder(PhotoEditor.this, new Runnable() {
@Override
public void run() {
- actionBar.clickButton(R.id.save_button);
+ actionBar.clickSave();
}
}, new Runnable() {
@@ -227,7 +201,7 @@ public class PhotoEditor extends Activity {
@Override
public void onBackPressed() {
- actionBar.clickButton(R.id.action_bar_back);
+ actionBar.clickBack();
}
@Override
diff --git a/src/com/android/gallery3d/photoeditor/RestorableView.java b/src/com/android/gallery3d/photoeditor/RestorableView.java
new file mode 100644
index 000000000..fc987414b
--- /dev/null
+++ b/src/com/android/gallery3d/photoeditor/RestorableView.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.photoeditor;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map.Entry;
+
+/**
+ * View that holds a single child and could be recreated/restored after orientation changes.
+ */
+public abstract class RestorableView extends FrameLayout {
+
+ private static final float ENABLED_ALPHA = 1;
+ private static final float DISABLED_ALPHA = 0.47f;
+
+ private final HashMap<Integer, Runnable> clickRunnables = new HashMap<Integer, Runnable>();
+ private final HashSet<Integer> changedViews = new HashSet<Integer>();
+ private final LayoutInflater inflater;
+
+ public RestorableView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ protected abstract int childLayoutId();
+
+ private void recreateChildView() {
+ if (getChildCount() != 0) {
+ removeAllViews();
+ }
+ inflater.inflate(childLayoutId(), this, true);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ recreateChildView();
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Remember the removing child before recreating the child.
+ View view = getChildAt(0);
+ recreateChildView();
+
+ // Restore its runnables and status of views that have been changed.
+ for (Entry<Integer, Runnable> entry : clickRunnables.entrySet()) {
+ setClickRunnable(entry.getKey(), entry.getValue());
+ }
+ for (int id : changedViews) {
+ View changed = view.findViewById(id);
+ setViewEnabled(id, changed.isEnabled());
+ setViewSelected(id, changed.isSelected());
+ }
+ }
+
+ public void setClickRunnable(int id, final Runnable r) {
+ findViewById(id).setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (isEnabled()) {
+ r.run();
+ }
+ }
+ });
+ clickRunnables.put(id, r);
+ }
+
+ public void setViewEnabled(int id, boolean enabled) {
+ View view = findViewById(id);
+ view.setEnabled(enabled);
+ view.setAlpha(enabled ? ENABLED_ALPHA : DISABLED_ALPHA);
+ // Track views whose enabled status has been updated.
+ changedViews.add(id);
+ }
+
+ public void setViewSelected(int id, boolean selected) {
+ findViewById(id).setSelected(selected);
+ // Track views whose selected status has been updated.
+ changedViews.add(id);
+ }
+}