diff options
Diffstat (limited to 'src/com/android/gallery3d/photoeditor/actions/EffectAction.java')
-rw-r--r-- | src/com/android/gallery3d/photoeditor/actions/EffectAction.java | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/photoeditor/actions/EffectAction.java b/src/com/android/gallery3d/photoeditor/actions/EffectAction.java new file mode 100644 index 000000000..6c6a893e3 --- /dev/null +++ b/src/com/android/gallery3d/photoeditor/actions/EffectAction.java @@ -0,0 +1,168 @@ +/* + * 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.actions; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.gallery3d.R; +import com.android.gallery3d.photoeditor.FilterStack; +import com.android.gallery3d.photoeditor.OnDoneCallback; +import com.android.gallery3d.photoeditor.filters.Filter; + +/** + * An action binding UI controls and effect operation for editing photo. + */ +public abstract class EffectAction extends LinearLayout { + + /** + * Listener of effect action. + */ + public interface Listener { + + void onClick(); + + void onDone(); + } + + protected EffectToolFactory factory; + + private Listener listener; + private Toast tooltip; + private FilterStack filterStack; + private boolean pushedFilter; + private FilterChangedCallback lastFilterChangedCallback; + + public EffectAction(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setListener(Listener l) { + listener = l; + findViewById(R.id.effect_button).setOnClickListener( + (listener == null) ? null : new View.OnClickListener() { + + @Override + public void onClick(View v) { + listener.onClick(); + } + }); + } + + public CharSequence name() { + return ((TextView) findViewById(R.id.effect_label)).getText(); + } + + public void begin(FilterStack filterStack, EffectToolFactory factory) { + // This view is already detached from UI view hierarchy by reaching here; findViewById() + // could only access its own child views from here. + this.filterStack = filterStack; + this.factory = factory; + + // Shows the tooltip if it's available. + if (getTag() != null) { + tooltip = Toast.makeText(getContext(), (String) getTag(), Toast.LENGTH_SHORT); + tooltip.setGravity(Gravity.CENTER, 0, 0); + tooltip.show(); + } + doBegin(); + } + + /** + * Ends the effect and then executes the runnable after the effect is finished. + */ + public void end(final Runnable runnableOnODone) { + doEnd(); + + // Wait till last output callback is done before finishing. + if ((lastFilterChangedCallback == null) || lastFilterChangedCallback.done) { + finish(runnableOnODone); + } else { + lastFilterChangedCallback.runnableOnReady = new Runnable() { + + @Override + public void run() { + finish(runnableOnODone); + } + }; + } + } + + private void finish(Runnable runnableOnDone) { + // Close the tooltip if it's still showing. + if ((tooltip != null) && (tooltip.getView().getParent() != null)) { + tooltip.cancel(); + tooltip = null; + } + pushedFilter = false; + lastFilterChangedCallback = null; + + runnableOnDone.run(); + } + + protected void notifyDone() { + if (listener != null) { + listener.onDone(); + } + } + + protected void notifyFilterChanged(Filter filter, boolean output) { + if (!pushedFilter && filter.isValid()) { + filterStack.pushFilter(filter); + pushedFilter = true; + } + if (pushedFilter && output) { + // Notify the stack to execute the changed top filter and output the results. + lastFilterChangedCallback = new FilterChangedCallback(); + filterStack.topFilterChanged(lastFilterChangedCallback); + } + } + + /** + * Subclasses should creates a specific filter and binds the filter to necessary UI controls + * here when the action is about to begin. + */ + protected abstract void doBegin(); + + /** + * Subclasses could do specific ending operations here when the action is about to end. + */ + protected abstract void doEnd(); + + /** + * Done callback for executing top filter changes. + */ + private class FilterChangedCallback implements OnDoneCallback { + + private boolean done; + private Runnable runnableOnReady; + + @Override + public void onDone() { + done = true; + + if (runnableOnReady != null) { + runnableOnReady.run(); + } + } + } +} |