1/*
2 * Copyright (C) 2016 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.googlecode.android_scripting;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.view.GestureDetector;
23import android.view.MotionEvent;
24import android.view.View;
25import android.view.GestureDetector.SimpleOnGestureListener;
26import android.view.View.OnTouchListener;
27
28import com.googlecode.android_scripting.activity.InterpreterManager;
29import com.googlecode.android_scripting.activity.LogcatViewer;
30import com.googlecode.android_scripting.activity.ScriptManager;
31import com.googlecode.android_scripting.activity.TriggerManager;
32
33import java.util.ArrayList;
34import java.util.HashMap;
35import java.util.Iterator;
36import java.util.List;
37import java.util.Map;
38
39public class ActivityFlinger {
40
41  private static final int SWIPE_MIN_DISTANCE = 120;
42  private static final int SWIPE_MAX_OFF_PATH = 100;
43  private static final int SWIPE_THRESHOLD_VELOCITY = 200;
44
45  private static class ActivityTransition {
46    Class<? extends Activity> mLeft;
47    Class<? extends Activity> mRight;
48
49    public ActivityTransition(Class<? extends Activity> left, Class<? extends Activity> right) {
50      mLeft = left;
51      mRight = right;
52    }
53  }
54
55  private static Map<Class<?>, ActivityTransition> mActivityTransitions =
56      new HashMap<Class<?>, ActivityTransition>();
57
58  private ActivityFlinger() {
59    // Utility class.
60  }
61
62  static {
63    List<Class<? extends Activity>> entries = new ArrayList<Class<? extends Activity>>();
64    entries.add(ScriptManager.class);
65    entries.add(InterpreterManager.class);
66    entries.add(TriggerManager.class);
67    entries.add(LogcatViewer.class);
68
69    Class<? extends Activity> left = null;
70    Class<? extends Activity> current = null;
71    Class<? extends Activity> right = null;
72
73    for (Iterator<Class<? extends Activity>> it = entries.iterator(); it.hasNext()
74        || current != null;) {
75      if (current == null) {
76        current = it.next();
77      }
78      if (it.hasNext()) {
79        right = it.next();
80      } else {
81        right = null;
82      }
83      mActivityTransitions.put(current, new ActivityTransition(left, right));
84      left = current;
85      current = right;
86    }
87  }
88
89  public static void attachView(View view, Context context) {
90    final LeftRightFlingListener mListener = new LeftRightFlingListener();
91    final GestureDetector mGestureDetector = new GestureDetector(mListener);
92    ActivityTransition transition = mActivityTransitions.get(context.getClass());
93    if (transition.mLeft != null) {
94      mListener.mLeftRunnable = new StartActivityRunnable(context, transition.mLeft);
95    }
96    if (transition.mRight != null) {
97      mListener.mRightRunnable = new StartActivityRunnable(context, transition.mRight);
98    }
99    view.setOnTouchListener(new OnTouchListener() {
100      @Override
101      public boolean onTouch(View v, MotionEvent event) {
102        return mGestureDetector.onTouchEvent(event);
103      }
104    });
105  }
106
107  private static class StartActivityRunnable implements Runnable {
108
109    private final Context mContext;
110    private final Class<?> mActivityClass;
111
112    private StartActivityRunnable(Context context, Class<?> activity) {
113      mContext = context;
114      mActivityClass = activity;
115    }
116
117    @Override
118    public void run() {
119      Intent intent = new Intent(mContext, mActivityClass);
120      mContext.startActivity(intent);
121    }
122  }
123
124  private static class LeftRightFlingListener extends SimpleOnGestureListener {
125    Runnable mLeftRunnable;
126    Runnable mRightRunnable;
127
128    @Override
129    public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
130      if (Math.abs(event1.getY() - event2.getY()) > SWIPE_MAX_OFF_PATH) {
131        return false;
132      }
133      if (event1.getX() - event2.getX() > SWIPE_MIN_DISTANCE
134          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
135        if (mRightRunnable != null) {
136          mRightRunnable.run();
137        }
138      } else if (event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE
139          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
140        if (mLeftRunnable != null) {
141          mLeftRunnable.run();
142        }
143      } else {
144        return super.onFling(event1, event2, velocityX, velocityY);
145      }
146      return true;
147    }
148  }
149}
150