Home | History | Annotate | Download | only in photoeditor
      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.photoeditor;
     18 
     19 import android.content.Context;
     20 import android.graphics.Bitmap;
     21 import android.net.Uri;
     22 import android.util.AttributeSet;
     23 import android.view.MotionEvent;
     24 import android.widget.RelativeLayout;
     25 
     26 import com.android.photoeditor.animation.FadeAnimation;
     27 import com.android.photoeditor.animation.Rotate3DAnimation;
     28 import com.android.photoeditor.animation.Rotate3DAnimation.Rotate;
     29 
     30 /**
     31  * Toolbar that contains all tools and handles all operations for editing photo.
     32  */
     33 public class Toolbar extends RelativeLayout {
     34 
     35     private static final int UNDO_REDO_ANIMATION_DURATION = 100;
     36     private static final int QUICKVIEW_ANIMATION_DURATION = 150;
     37 
     38     private final FilterStack filterStack = new FilterStack();
     39     private ToolbarLayoutHandler layoutHandler;
     40     private ToolbarIdleHandler idleHandler;
     41     private EffectsBar effectsBar;
     42     private ActionBar actionBar;
     43     private PhotoView photoView;
     44     private SpinnerProgressDialog progressDialog;
     45     private Uri sourceUri;
     46 
     47     public Toolbar(Context context, AttributeSet attrs) {
     48         super(context, attrs);
     49     }
     50 
     51     @Override
     52     public boolean onInterceptTouchEvent(MotionEvent ev) {
     53         idleHandler.killIdle();
     54         return false;
     55     }
     56 
     57     @Override
     58     protected void onLayout(boolean changed, int l, int t, int r, int b) {
     59         super.onLayout(changed, l, t, r, b);
     60 
     61         layoutHandler.extraLayout(l, t, r, b);
     62     }
     63 
     64     public void initialize() {
     65         photoView = (PhotoView) findViewById(R.id.photo_view);
     66         initializeEffectsBar();
     67         initializeActionBar();
     68         layoutHandler = new ToolbarLayoutHandler(this);
     69         idleHandler = new ToolbarIdleHandler(this);
     70         idleHandler.killIdle();
     71     }
     72 
     73     private void initializeEffectsBar() {
     74         effectsBar = (EffectsBar) findViewById(R.id.effects_bar);
     75         effectsBar.initialize(filterStack, photoView, this);
     76     }
     77 
     78     private void initializeActionBar() {
     79         final PhotoOutputCallback callback = new PhotoOutputCallback() {
     80 
     81             @Override
     82             public void onReady(Photo photo) {
     83                 photoView.setTransitionAnimations(
     84                         FadeAnimation.getFadeOutInAnimations(UNDO_REDO_ANIMATION_DURATION));
     85                 photoView.update(photo);
     86                 progressDialog.dismiss();
     87             }
     88         };
     89 
     90         actionBar = (ActionBar) findViewById(R.id.action_bar);
     91         actionBar.initialize(new ActionBar.ActionBarListener() {
     92 
     93             @Override
     94             public void onUndo() {
     95                 effectsBar.effectsOff(new Runnable() {
     96 
     97                     @Override
     98                     public void run() {
     99                         progressDialog = SpinnerProgressDialog.show(Toolbar.this);
    100                         filterStack.undo(callback);
    101                     }
    102                 });
    103             }
    104 
    105             @Override
    106             public void onRedo() {
    107                 effectsBar.effectsOff(new Runnable() {
    108 
    109                     @Override
    110                     public void run() {
    111                         progressDialog = SpinnerProgressDialog.show(Toolbar.this);
    112                         filterStack.redo(callback);
    113                     }
    114                 });
    115             }
    116 
    117             @Override
    118             public void onQuickview(final boolean on) {
    119                 final PhotoOutputCallback callback = new PhotoOutputCallback() {
    120 
    121                     @Override
    122                     public void onReady(Photo photo) {
    123                         photoView.setTransitionAnimations(Rotate3DAnimation.getFlipAnimations(
    124                                 on ? Rotate.RIGHT : Rotate.LEFT, QUICKVIEW_ANIMATION_DURATION));
    125                         photoView.update(photo);
    126                     }
    127                 };
    128 
    129                 if (on) {
    130                     effectsBar.effectsOff(new Runnable() {
    131 
    132                         @Override
    133                         public void run() {
    134                             effectsBar.setVisibility(INVISIBLE);
    135                             filterStack.getSourceCopy(callback);
    136                         }
    137                     });
    138                 } else {
    139                     effectsBar.setVisibility(VISIBLE);
    140                     filterStack.getResultCopy(callback);
    141                 }
    142             }
    143 
    144             @Override
    145             public void onSave() {
    146                 effectsBar.effectsOff(new Runnable() {
    147 
    148                     @Override
    149                     public void run() {
    150                         savePhoto(null);
    151                     }
    152                 });
    153             }
    154         });
    155     }
    156 
    157     public void openPhoto(Uri uri) {
    158         sourceUri = uri;
    159         filterStack.setStackListener(actionBar);
    160 
    161         // clearPhotoSource() should be called before loading a new source photo to avoid OOM.
    162         progressDialog = SpinnerProgressDialog.show(this);
    163         filterStack.clearPhotoSource();
    164         new LoadScreennailTask(getContext(), new LoadScreennailTask.Callback() {
    165 
    166             @Override
    167             public void onComplete(Bitmap bitmap) {
    168                 filterStack.setPhotoSource(Photo.create(bitmap));
    169                 filterStack.getResultCopy(new PhotoOutputCallback() {
    170 
    171                     @Override
    172                     public void onReady(Photo photo) {
    173                         photoView.update(photo);
    174                         progressDialog.dismiss();
    175                         effectsBar.setEnabled(photo != null);
    176                     }
    177                 });
    178             }
    179         }).execute(sourceUri);
    180     }
    181 
    182     /**
    183      * Saves photo and executes runnable (if provided) after saving done.
    184      */
    185     public void savePhoto(final Runnable runnable) {
    186         progressDialog = SpinnerProgressDialog.show(this);
    187         filterStack.getResultCopy(new PhotoOutputCallback() {
    188 
    189             @Override
    190             public void onReady(Photo photo) {
    191                 new SaveCopyTask(getContext(), sourceUri, new SaveCopyTask.Callback() {
    192 
    193                     @Override
    194                     public void onComplete(Uri uri) {
    195                         // TODO: Handle saving failure.
    196                         progressDialog.dismiss();
    197                         actionBar.disableSave();
    198                         if (runnable != null) {
    199                             runnable.run();
    200                         }
    201                     }
    202                 }).execute(photo);
    203             }
    204         });
    205     }
    206 }
    207