1/*
2 * Copyright (C) 2017 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 androidx.wear.widget.drawer;
18
19import android.view.View;
20import android.widget.AbsListView;
21import android.widget.ScrollView;
22
23import androidx.annotation.Nullable;
24import androidx.annotation.RestrictTo;
25import androidx.annotation.RestrictTo.Scope;
26import androidx.core.widget.NestedScrollView;
27import androidx.recyclerview.widget.RecyclerView;
28
29import java.util.Map;
30import java.util.WeakHashMap;
31
32/**
33 * Creates a {@link FlingWatcher} based on the type of {@link View}.
34 *
35 * @hide
36 */
37@RestrictTo(Scope.LIBRARY)
38class FlingWatcherFactory {
39
40    /**
41     * Listener that is notified when a fling completes and the view has settled. Polling may be
42     * used to determine when the fling has completed, so there may be up to a 100ms delay.
43     */
44    interface FlingListener {
45        void onFlingComplete(View view);
46    }
47
48    /**
49     * Watches a given {@code view} to detect the end of a fling. Will notify a {@link
50     * FlingListener} when the end is found.
51     */
52    interface FlingWatcher {
53        void watch();
54    }
55
56    private final FlingListener mListener;
57    private final Map<View, FlingWatcher> mWatchers = new WeakHashMap<>();
58
59    FlingWatcherFactory(FlingListener listener) {
60        if (listener == null) {
61            throw new IllegalArgumentException("FlingListener was null");
62        }
63
64        mListener = listener;
65    }
66
67    /**
68     * Returns a {@link FlingWatcher} for the particular type of {@link View}.
69     */
70    @Nullable
71    FlingWatcher getFor(View view) {
72        FlingWatcher watcher = mWatchers.get(view);
73        if (watcher == null) {
74            watcher = createFor(view);
75            if (watcher != null) {
76                mWatchers.put(view, watcher);
77            }
78        }
79
80        return watcher;
81    }
82
83    /**
84     * Creates a {@link FlingWatcher} for the particular type of {@link View}.
85     */
86    @Nullable
87    private FlingWatcher createFor(View view) {
88        if (view == null) {
89            throw new IllegalArgumentException("View was null");
90        }
91
92        if (view instanceof RecyclerView) {
93            return new RecyclerViewFlingWatcher(mListener, (RecyclerView) view);
94        } else if (view instanceof AbsListView) {
95            return new AbsListViewFlingWatcher(mListener, (AbsListView) view);
96        } else if (view instanceof ScrollView) {
97            return new ScrollViewFlingWatcher(mListener, (ScrollView) view);
98        } else if (view instanceof NestedScrollView) {
99            return new NestedScrollViewFlingWatcher(mListener, (NestedScrollView) view);
100        } else {
101            return null;
102        }
103    }
104}
105