diff options
Diffstat (limited to 'src/com')
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); + } +} |