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
17package com.android.gallery3d.photoeditor.actions;
18
19import android.content.Context;
20import android.util.AttributeSet;
21
22import com.android.gallery3d.R;
23import com.android.gallery3d.photoeditor.PhotoView;
24import com.android.gallery3d.photoeditor.filters.RotateFilter;
25
26/**
27 * An action handling rotate effect.
28 */
29public class RotateAction extends EffectAction {
30
31    private static final float DEFAULT_ANGLE = 0.0f;
32    private static final float DEFAULT_ROTATE_SPAN = 360.0f;
33
34    private RotateFilter filter;
35    private float rotateDegrees;
36    private Runnable queuedRotationChange;
37    private RotateView rotateView;
38
39    public RotateAction(Context context, AttributeSet attrs) {
40        super(context, attrs);
41    }
42
43    @Override
44    public void doBegin() {
45        filter = new RotateFilter();
46
47        rotateView = factory.createRotateView();
48        rotateView.setOnRotateChangeListener(new RotateView.OnRotateChangeListener() {
49
50            // Directly transform photo-view because running the rotate filter isn't fast enough.
51            PhotoView photoView = (PhotoView) rotateView.getRootView().findViewById(
52                    R.id.photo_view);
53
54            @Override
55            public void onAngleChanged(float degrees, boolean fromUser){
56                if (fromUser) {
57                    rotateDegrees = degrees;
58                    updateRotateFilter(false);
59                    transformPhotoView(degrees);
60                }
61            }
62
63            @Override
64            public void onStartTrackingTouch() {
65                // no-op
66            }
67
68            @Override
69            public void onStopTrackingTouch() {
70                roundRotateDegrees();
71                updateRotateFilter(false);
72                transformPhotoView(rotateDegrees);
73                rotateView.setRotatedAngle(rotateDegrees);
74            }
75
76            private void transformPhotoView(final float degrees) {
77                // Remove the outdated rotation change before queuing a new one.
78                if (queuedRotationChange != null) {
79                    photoView.remove(queuedRotationChange);
80                }
81                queuedRotationChange = new Runnable() {
82
83                    @Override
84                    public void run() {
85                        photoView.rotatePhoto(degrees);
86                    }
87                };
88                photoView.queue(queuedRotationChange);
89            }
90        });
91        rotateView.setRotatedAngle(DEFAULT_ANGLE);
92        rotateView.setRotateSpan(DEFAULT_ROTATE_SPAN);
93        rotateDegrees = 0;
94        queuedRotationChange = null;
95    }
96
97    @Override
98    public void doEnd() {
99        rotateView.setOnRotateChangeListener(null);
100        // Round the current rotation degrees in case rotation tracking has not stopped yet.
101        roundRotateDegrees();
102        updateRotateFilter(true);
103    }
104
105    /**
106     * Rounds rotate degrees to multiples of 90 degrees.
107     */
108    private void roundRotateDegrees() {
109        if (rotateDegrees % 90 != 0) {
110            rotateDegrees = Math.round(rotateDegrees / 90) * 90;
111        }
112    }
113
114    private void updateRotateFilter(boolean outputFilter) {
115        filter.setAngle(rotateDegrees);
116        notifyFilterChanged(filter, outputFilter);
117    }
118}
119