1/*
2 * Copyright (C) 2008 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.calculator2;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.view.GestureDetector;
22import android.view.MotionEvent;
23import android.view.View;
24import android.view.animation.AccelerateDecelerateInterpolator;
25import android.view.animation.Animation;
26import android.view.animation.Animation.AnimationListener;
27import android.view.animation.TranslateAnimation;
28import android.widget.FrameLayout;
29
30class PanelSwitcher extends FrameLayout implements AnimationListener {
31    private static final int MAJOR_MOVE = 60;
32    private static final int ANIM_DURATION = 400;
33
34    private GestureDetector mGestureDetector;
35    private int mCurrentView;
36    private View mChildren[] = new View[0];
37
38    private int mWidth;
39    private TranslateAnimation inLeft;
40    private TranslateAnimation outLeft;
41
42    private TranslateAnimation inRight;
43    private TranslateAnimation outRight;
44
45    private static final int LEFT  = 1;
46    private static final int RIGHT = 2;
47    private int mPreviousMove;
48
49    public interface Listener {
50        void onChange();
51    }
52
53    private Listener mListener;
54
55    public PanelSwitcher(Context context, AttributeSet attrs) {
56        super(context, attrs);
57        mCurrentView = 0;
58        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
59                @Override
60                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
61                                       float velocityY) {
62                    int dx = (int) (e2.getX() - e1.getX());
63
64                    // don't accept the fling if it's too short
65                    // as it may conflict with a button push
66                    if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.abs(velocityY)) {
67                        if (velocityX > 0) {
68                            moveRight();
69                        } else {
70                            moveLeft();
71                        }
72                        return true;
73                    } else {
74                        return false;
75                    }
76                }
77            });
78    }
79
80    public void setListener(Listener listener) {
81        this.mListener = listener;
82    }
83
84    void setCurrentIndex(int current) {
85        boolean changed = mCurrentView != current;
86        mCurrentView = current;
87        updateCurrentView();
88        if (changed && mListener != null) {
89            mListener.onChange();
90        }
91    }
92
93    private void updateCurrentView() {
94        for (int i = mChildren.length-1; i >= 0 ; --i) {
95            mChildren[i].setVisibility(i==mCurrentView ? View.VISIBLE : View.GONE);
96        }
97    }
98
99    @Override
100    public void onSizeChanged(int w, int h, int oldW, int oldH) {
101        mWidth = w;
102        inLeft   = new TranslateAnimation(mWidth, 0, 0, 0);
103        inLeft.setAnimationListener(this);
104        outLeft  = new TranslateAnimation(0, -mWidth, 0, 0);
105        inRight  = new TranslateAnimation(-mWidth, 0, 0, 0);
106        inRight.setAnimationListener(this);
107        outRight = new TranslateAnimation(0, mWidth, 0, 0);
108
109        inLeft.setDuration(ANIM_DURATION);
110        outLeft.setDuration(ANIM_DURATION);
111        inRight.setDuration(ANIM_DURATION);
112        outRight.setDuration(ANIM_DURATION);
113    }
114
115    @Override
116    protected void onFinishInflate() {
117        int count = getChildCount();
118        mChildren = new View[count];
119        for (int i = 0; i < count; ++i) {
120            mChildren[i] = getChildAt(i);
121        }
122        updateCurrentView();
123    }
124
125    @Override
126    public boolean onTouchEvent(MotionEvent event) {
127        mGestureDetector.onTouchEvent(event);
128        return true;
129    }
130
131    @Override
132    public boolean onInterceptTouchEvent(MotionEvent event) {
133        return mGestureDetector.onTouchEvent(event);
134    }
135
136    void moveLeft() {
137        //  <--
138        if (mCurrentView < mChildren.length - 1 && mPreviousMove != LEFT) {
139            mChildren[mCurrentView+1].setVisibility(View.VISIBLE);
140            mChildren[mCurrentView+1].startAnimation(inLeft);
141            mChildren[mCurrentView].startAnimation(outLeft);
142            mChildren[mCurrentView].setVisibility(View.GONE);
143
144            mCurrentView++;
145            mPreviousMove = LEFT;
146        }
147    }
148
149    void moveRight() {
150        //  -->
151        if (mCurrentView > 0 && mPreviousMove != RIGHT) {
152            mChildren[mCurrentView-1].setVisibility(View.VISIBLE);
153            mChildren[mCurrentView-1].startAnimation(inRight);
154            mChildren[mCurrentView].startAnimation(outRight);
155            mChildren[mCurrentView].setVisibility(View.GONE);
156
157            mCurrentView--;
158            mPreviousMove = RIGHT;
159        }
160    }
161
162    int getCurrentIndex() {
163        return mCurrentView;
164    }
165
166    @Override
167    public void onAnimationRepeat(Animation animation) {
168    }
169
170    @Override
171    public void onAnimationStart(Animation animation) {
172    }
173
174    @Override
175    public void onAnimationEnd(Animation animation) {
176        if (mListener != null) {
177            mListener.onChange();
178        }
179    }
180}
181