// Path: library/src/main/java/com/google/android/material/motion/MotionObserver.java
// public abstract class MotionObserver<T> extends Observer<T> {
// 
//   @Override
//   public abstract void next(T value);
// 
//   public abstract void build(MotionBuilder<T> builder, T... values);
// 
//   /**
//    * A simple observer for when you only want to implement {@link #next(Object)}.
//    */
//   public static abstract class SimpleMotionObserver<T> extends MotionObserver<T> {
//     @Override
//     public void build(MotionBuilder<T> builder, T[] values) {
//     }
//   }
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/Source.java
// public abstract class Source<T> {
// 
//   private final Interaction<?, T> interaction;
// 
//   public Source(Interaction<?, T> interaction) {
//     this.interaction = interaction;
//   }
// 
//   public final MotionObservable<T> getStream() {
//     return new MotionObservable<>(new Connector<MotionObserver<T>>() {
// 
//       @NonNull
//       @Override
//       public Disconnector connect(final MotionObserver<T> observer) {
//         onConnect(observer);
// 
//         final Subscription enabledSubscription = interaction.enabled.getStream()
//           .compose(dedupe())
//           .subscribe(new SimpleMotionObserver<Boolean>() {
//             @Override
//             public void next(Boolean enabled) {
//               if (enabled) {
//                 onEnable();
//               } else {
//                 onDisable();
//               }
//             }
//           });
// 
//         return new Disconnector() {
// 
//           @Override
//           public void disconnect() {
// 
//             enabledSubscription.unsubscribe();
//             // TODO: This will potentially cause onDisable() to be called twice.
//             onDisable();
//             onDisconnect(observer);
//           }
//         };
//       }
//     });
//   }
// 
//   protected abstract void onConnect(MotionObserver<T> observer);
// 
//   protected abstract void onEnable();
// 
//   protected abstract void onDisable();
// 
//   protected abstract void onDisconnect(MotionObserver<T> observer);
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/gestures/OnTouchListeners.java
// public class OnTouchListeners {
// 
//   public static void add(View view, OnTouchListener listener) {
//     getMultiListener(view).addOnTouchListener(listener);
//   }
// 
//   public static void remove(View view, OnTouchListener listener) {
//     getMultiListener(view).removeOnTouchListener(listener);
//   }
// 
//   @NonNull
//   private static MultiOnTouchListener getMultiListener(View view) {
//     // View.getOnTouchListener() does not exist, so we store the listener in a tag.
//     MultiOnTouchListener multiListener = (MultiOnTouchListener) view.getTag(R.id.multi_listener_tag);
//     if (multiListener == null) {
//       multiListener = new MultiOnTouchListener();
//       view.setTag(R.id.multi_listener_tag, multiListener);
//     }
//     view.setOnTouchListener(multiListener);
//     return multiListener;
//   }
// 
//   private static class MultiOnTouchListener implements OnTouchListener {
// 
//     private final List<OnTouchListener> listeners = new CopyOnWriteArrayList<>();
// 
//     @Override
//     public boolean onTouch(View v, MotionEvent event) {
//       boolean handled = false;
// 
//       for (OnTouchListener listener : listeners) {
//         handled |= listener.onTouch(v, event);
//       }
// 
//       return handled;
//     }
// 
//     public void addOnTouchListener(OnTouchListener listener) {
//       if (!listeners.contains(listener)) {
//         listeners.add(listener);
//       }
//     }
// 
//     public void removeOnTouchListener(OnTouchListener listener) {
//       listeners.remove(listener);
//     }
//   }
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/interactions/SetPositionOnTap.java
// public class SetPositionOnTap extends Interaction<ReactiveProperty<PointF>, PointF> {
// 
//   public final View container;
//   public final MotionObservable<PointF> tapStream;
// 
//   public SetPositionOnTap(View container) {
//     this.container = container;
//     this.tapStream = new TapSource(this).getStream();
//   }
// 
//   @Override
//   public void apply(
//     MotionRuntime runtime,
//     ReactiveProperty<PointF> target,
//     ConstraintApplicator<PointF> constraints) {
//     runtime.write(constraints.apply(tapStream), target);
//   }
// }


import android.graphics.PointF;
import android.support.v4.util.SimpleArrayMap;
import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import com.google.android.indefinite.observable.Observer;
import com.google.android.material.motion.MotionObserver;
import com.google.android.material.motion.MotionState;
import com.google.android.material.motion.Source;
import com.google.android.material.motion.gestures.OnTouchListeners;
import com.google.android.material.motion.interactions.SetPositionOnTap;
/*
 * Copyright 2017-present The Material Motion Authors. All Rights Reserved.
 *
 * 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.google.android.material.motion.sources;



public class TapSource extends Source<PointF> {

  private final SetPositionOnTap interaction;

  private final View container;
  private final GestureDetectorCompat detector;
  private final SimpleArrayMap<Observer<PointF>, OnGestureListener> gestureListeners =
    new SimpleArrayMap<>();

// Path: library/src/main/java/com/google/android/material/motion/MotionObserver.java
// public abstract class MotionObserver<T> extends Observer<T> {
// 
//   @Override
//   public abstract void next(T value);
// 
//   public abstract void build(MotionBuilder<T> builder, T... values);
// 
//   /**
//    * A simple observer for when you only want to implement {@link #next(Object)}.
//    */
//   public static abstract class SimpleMotionObserver<T> extends MotionObserver<T> {
//     @Override
//     public void build(MotionBuilder<T> builder, T[] values) {
//     }
//   }
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/Source.java
// public abstract class Source<T> {
// 
//   private final Interaction<?, T> interaction;
// 
//   public Source(Interaction<?, T> interaction) {
//     this.interaction = interaction;
//   }
// 
//   public final MotionObservable<T> getStream() {
//     return new MotionObservable<>(new Connector<MotionObserver<T>>() {
// 
//       @NonNull
//       @Override
//       public Disconnector connect(final MotionObserver<T> observer) {
//         onConnect(observer);
// 
//         final Subscription enabledSubscription = interaction.enabled.getStream()
//           .compose(dedupe())
//           .subscribe(new SimpleMotionObserver<Boolean>() {
//             @Override
//             public void next(Boolean enabled) {
//               if (enabled) {
//                 onEnable();
//               } else {
//                 onDisable();
//               }
//             }
//           });
// 
//         return new Disconnector() {
// 
//           @Override
//           public void disconnect() {
// 
//             enabledSubscription.unsubscribe();
//             // TODO: This will potentially cause onDisable() to be called twice.
//             onDisable();
//             onDisconnect(observer);
//           }
//         };
//       }
//     });
//   }
// 
//   protected abstract void onConnect(MotionObserver<T> observer);
// 
//   protected abstract void onEnable();
// 
//   protected abstract void onDisable();
// 
//   protected abstract void onDisconnect(MotionObserver<T> observer);
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/gestures/OnTouchListeners.java
// public class OnTouchListeners {
// 
//   public static void add(View view, OnTouchListener listener) {
//     getMultiListener(view).addOnTouchListener(listener);
//   }
// 
//   public static void remove(View view, OnTouchListener listener) {
//     getMultiListener(view).removeOnTouchListener(listener);
//   }
// 
//   @NonNull
//   private static MultiOnTouchListener getMultiListener(View view) {
//     // View.getOnTouchListener() does not exist, so we store the listener in a tag.
//     MultiOnTouchListener multiListener = (MultiOnTouchListener) view.getTag(R.id.multi_listener_tag);
//     if (multiListener == null) {
//       multiListener = new MultiOnTouchListener();
//       view.setTag(R.id.multi_listener_tag, multiListener);
//     }
//     view.setOnTouchListener(multiListener);
//     return multiListener;
//   }
// 
//   private static class MultiOnTouchListener implements OnTouchListener {
// 
//     private final List<OnTouchListener> listeners = new CopyOnWriteArrayList<>();
// 
//     @Override
//     public boolean onTouch(View v, MotionEvent event) {
//       boolean handled = false;
// 
//       for (OnTouchListener listener : listeners) {
//         handled |= listener.onTouch(v, event);
//       }
// 
//       return handled;
//     }
// 
//     public void addOnTouchListener(OnTouchListener listener) {
//       if (!listeners.contains(listener)) {
//         listeners.add(listener);
//       }
//     }
// 
//     public void removeOnTouchListener(OnTouchListener listener) {
//       listeners.remove(listener);
//     }
//   }
// }
// 
// Path: library/src/main/java/com/google/android/material/motion/interactions/SetPositionOnTap.java
// public class SetPositionOnTap extends Interaction<ReactiveProperty<PointF>, PointF> {
// 
//   public final View container;
//   public final MotionObservable<PointF> tapStream;
// 
//   public SetPositionOnTap(View container) {
//     this.container = container;
//     this.tapStream = new TapSource(this).getStream();
//   }
// 
//   @Override
//   public void apply(
//     MotionRuntime runtime,
//     ReactiveProperty<PointF> target,
//     ConstraintApplicator<PointF> constraints) {
//     runtime.write(constraints.apply(tapStream), target);
//   }
// }


// Path: library/src/main/java/com/google/android/material/motion/sources/TapSource.java
import android.graphics.PointF;
import android.support.v4.util.SimpleArrayMap;
import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import com.google.android.indefinite.observable.Observer;
import com.google.android.material.motion.MotionObserver;
import com.google.android.material.motion.MotionState;
import com.google.android.material.motion.Source;
import com.google.android.material.motion.gestures.OnTouchListeners;
import com.google.android.material.motion.interactions.SetPositionOnTap;

/*
 * Copyright 2017-present The Material Motion Authors. All Rights Reserved.
 *
 * 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.google.android.material.motion.sources;



public class TapSource extends Source<PointF> {

  private final SetPositionOnTap interaction;

  private final View container;
  private final GestureDetectorCompat detector;
  private final SimpleArrayMap<Observer<PointF>, OnGestureListener> gestureListeners =
    new SimpleArrayMap<>();

  public TapSource(SetPositionOnTap interaction) {