1 /*
2  * Copyright 2024 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 
17 package androidx.recyclerview.selection;
18 
19 import static android.view.InputDevice.SOURCE_MOUSE;
20 import static android.view.InputDevice.SOURCE_UNKNOWN;
21 import static android.view.MotionEvent.TOOL_TYPE_ERASER;
22 import static android.view.MotionEvent.TOOL_TYPE_FINGER;
23 import static android.view.MotionEvent.TOOL_TYPE_MOUSE;
24 import static android.view.MotionEvent.TOOL_TYPE_STYLUS;
25 import static android.view.MotionEvent.TOOL_TYPE_UNKNOWN;
26 
27 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
28 
29 import android.view.InputDevice;
30 import android.view.MotionEvent;
31 
32 import androidx.annotation.IntDef;
33 import androidx.annotation.RestrictTo;
34 
35 import org.jspecify.annotations.NonNull;
36 
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 import java.util.Objects;
40 
41 /**
42  * Enables storing multiple {@link MotionEvent} parameters (e.g.
43  * {@link MotionEvent#getToolType(int)}) as a key in a map. This opens up the ability to map
44  * these multiple parameters against their respective handlers. For example some events behave
45  * differently based on their toolType and source where others just require toolType.
46  */
47 @RestrictTo(LIBRARY)
48 public class ToolSourceKey {
49     private final @ToolType int mToolType;
50     private final @Source int mSource;
51 
ToolSourceKey(@oolType int toolType)52     ToolSourceKey(@ToolType int toolType) {
53         mToolType = toolType;
54         mSource = InputDevice.SOURCE_UNKNOWN;
55     }
56 
ToolSourceKey(@oolType int toolType, @Source int source)57     ToolSourceKey(@ToolType int toolType, @Source int source) {
58         mToolType = toolType;
59         mSource = source;
60     }
61 
62     /**
63      * Create a `ToolSourceKey` from a supplied `MotionEvent`.
64      *
65      * @return {@link ToolSourceKey}
66      */
fromMotionEvent(@onNull MotionEvent e)67     public static @NonNull ToolSourceKey fromMotionEvent(@NonNull MotionEvent e) {
68         return new ToolSourceKey(e.getToolType(0), e.getSource());
69     }
70 
getToolType()71     public int getToolType() {
72         return mToolType;
73     }
74 
getSource()75     public int getSource() {
76         return mSource;
77     }
78 
79     @Override
hashCode()80     public int hashCode() {
81         return Objects.hash(mToolType, mSource);
82     }
83 
84     @Override
equals(Object obj)85     public boolean equals(Object obj) {
86         if (this == obj) {
87             return true;
88         }
89         if (!(obj instanceof ToolSourceKey)) {
90             return false;
91         }
92         ToolSourceKey matcher = (ToolSourceKey) obj;
93         return mToolType == matcher.getToolType() && mSource == matcher.getSource();
94     }
95 
96     @Override
toString()97     public @NonNull String toString() {
98         return String.valueOf(mToolType) + "," + String.valueOf(mSource);
99     }
100 
101     @IntDef(value = {TOOL_TYPE_FINGER, TOOL_TYPE_MOUSE, TOOL_TYPE_ERASER, TOOL_TYPE_STYLUS,
102             TOOL_TYPE_UNKNOWN})
103     @Retention(RetentionPolicy.SOURCE)
104     @interface ToolType {
105     }
106 
107     /**
108      * Please add additional sources here from InputDevice.SOURCE_*.
109      */
110     @IntDef(value = {SOURCE_MOUSE, SOURCE_UNKNOWN})
111     @Retention(RetentionPolicy.SOURCE)
112     @interface Source {
113     }
114 }
115