1 /*
2  * Copyright 2018 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.core.view;
18 
19 import static android.os.Build.VERSION.SDK_INT;
20 
21 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
22 
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.graphics.Bitmap;
26 import android.view.PointerIcon;
27 
28 import androidx.annotation.RequiresApi;
29 import androidx.annotation.RestrictTo;
30 
31 import org.jspecify.annotations.NonNull;
32 import org.jspecify.annotations.Nullable;
33 
34 /**
35  * Helper for accessing features in {@link PointerIcon} in a backwards compatible
36  * fashion.
37  */
38 public final class PointerIconCompat {
39     /** Synonym for {@link PointerIcon#TYPE_NULL} */
40     public static final int TYPE_NULL = 0;
41 
42     /** Synonym for {@link PointerIcon#TYPE_ARROW} */
43     public static final int TYPE_ARROW = 1000;
44 
45     /** Synonym for {@link PointerIcon#TYPE_CONTEXT_MENU} */
46     public static final int TYPE_CONTEXT_MENU = 1001;
47 
48     /** Synonym for {@link PointerIcon#TYPE_HAND} */
49     public static final int TYPE_HAND = 1002;
50 
51     /** Synonym for {@link PointerIcon#TYPE_HELP} */
52     public static final int TYPE_HELP = 1003;
53 
54     /** Synonym for {@link PointerIcon#TYPE_WAIT} */
55     public static final int TYPE_WAIT = 1004;
56 
57     /** Synonym for {@link PointerIcon#TYPE_CELL} */
58     public static final int TYPE_CELL = 1006;
59 
60     /** Synonym for {@link PointerIcon#TYPE_CROSSHAIR} */
61     public static final int TYPE_CROSSHAIR = 1007;
62 
63     /** Synonym for {@link PointerIcon#TYPE_TEXT} */
64     public static final int TYPE_TEXT = 1008;
65 
66     /** Synonym for {@link PointerIcon#TYPE_VERTICAL_TEXT} */
67     public static final int TYPE_VERTICAL_TEXT = 1009;
68 
69     /** Synonym for {@link PointerIcon#TYPE_ALIAS} */
70     public static final int TYPE_ALIAS = 1010;
71 
72     /** Synonym for {@link PointerIcon#TYPE_COPY} */
73     public static final int TYPE_COPY = 1011;
74 
75     /** Synonym for {@link PointerIcon#TYPE_NO_DROP} */
76     public static final int TYPE_NO_DROP = 1012;
77 
78     /** Synonym for {@link PointerIcon#TYPE_ALL_SCROLL} */
79     public static final int TYPE_ALL_SCROLL = 1013;
80 
81     /** Synonym for {@link PointerIcon#TYPE_HORIZONTAL_DOUBLE_ARROW} */
82     public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014;
83 
84     /** Synonym for {@link PointerIcon#TYPE_VERTICAL_DOUBLE_ARROW} */
85     public static final int TYPE_VERTICAL_DOUBLE_ARROW = 1015;
86 
87     /** Synonym for {@link PointerIcon#TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW} */
88     public static final int TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016;
89 
90     /** Synonym for {@link PointerIcon#TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW} */
91     public static final int TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017;
92 
93     /** Synonym for {@link PointerIcon#TYPE_ZOOM_IN} */
94     public static final int TYPE_ZOOM_IN = 1018;
95 
96     /** Synonym for {@link PointerIcon#TYPE_ZOOM_OUT} */
97     public static final int TYPE_ZOOM_OUT = 1019;
98 
99     /** Synonym for {@link PointerIcon#TYPE_GRAB} */
100     public static final int TYPE_GRAB = 1020;
101 
102     /** Synonym for {@link PointerIcon#TYPE_GRABBING} */
103     public static final int TYPE_GRABBING = 1021;
104 
105     /** Synonym for {@link PointerIcon#TYPE_DEFAULT} */
106     public static final int TYPE_DEFAULT = TYPE_ARROW;
107 
108     private final PointerIcon mPointerIcon;
109 
PointerIconCompat(PointerIcon pointerIcon)110     private PointerIconCompat(PointerIcon pointerIcon) {
111         mPointerIcon = pointerIcon;
112     }
113 
114     /**
115      */
116     @RestrictTo(LIBRARY_GROUP_PREFIX)
getPointerIcon()117     public @Nullable Object getPointerIcon() {
118         return mPointerIcon;
119     }
120 
121     /**
122      * Gets a system pointer icon for the given style.
123      * If style is not recognized, returns the default pointer icon.
124      *
125      * @param context The context.
126      * @param style The pointer icon style.
127      * @return The pointer icon.
128      */
getSystemIcon(@onNull Context context, int style)129     public static @NonNull PointerIconCompat getSystemIcon(@NonNull Context context, int style) {
130         if (SDK_INT >= 24) {
131             return new PointerIconCompat(Api24Impl.getSystemIcon(context, style));
132         } else {
133             return new PointerIconCompat(null);
134         }
135     }
136 
137     /**
138      * Creates a custom pointer from the given bitmap and hotspot information.
139      *
140      * @param bitmap The bitmap for the icon.
141      * @param hotSpotX The X offset of the pointer icon hotspot in the bitmap.
142      *        Must be within the [0, bitmap.getWidth()) range.
143      * @param hotSpotY The Y offset of the pointer icon hotspot in the bitmap.
144      *        Must be within the [0, bitmap.getHeight()) range.
145      * @return A pointer icon for this bitmap.
146      *
147      * @throws IllegalArgumentException if bitmap is null, or if the x/y hotspot
148      *         parameters are invalid.
149      */
create(@onNull Bitmap bitmap, float hotSpotX, float hotSpotY)150     public static @NonNull PointerIconCompat create(@NonNull Bitmap bitmap, float hotSpotX,
151             float hotSpotY) {
152         if (SDK_INT >= 24) {
153             return new PointerIconCompat(Api24Impl.create(bitmap, hotSpotX, hotSpotY));
154         } else {
155             return new PointerIconCompat(null);
156         }
157     }
158 
159     /**
160      * Loads a custom pointer icon from an XML resource.
161      * <p>
162      * The XML resource should have the following form:
163      * <code>
164      * &lt;?xml version="1.0" encoding="utf-8"?&gt;
165      * &lt;pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
166      *   android:bitmap="@drawable/my_pointer_bitmap"
167      *   android:hotSpotX="24"
168      *   android:hotSpotY="24" /&gt;
169      * </code>
170      * </p>
171      *
172      * @param resources The resources object.
173      * @param resourceId The resource id.
174      * @return The pointer icon.
175      *
176      * @throws Resources.NotFoundException if the resource was not found or the drawable
177      * linked in the resource was not found.
178      */
load(@onNull Resources resources, int resourceId)179     public static @NonNull PointerIconCompat load(@NonNull Resources resources, int resourceId) {
180         if (SDK_INT >= 24) {
181             return new PointerIconCompat(Api24Impl.load(resources, resourceId));
182         } else {
183             return new PointerIconCompat(null);
184         }
185     }
186 
187     @RequiresApi(24)
188     static class Api24Impl {
Api24Impl()189         private Api24Impl() {
190             // This class is not instantiable.
191         }
192 
getSystemIcon(Context context, int type)193         static PointerIcon getSystemIcon(Context context, int type) {
194             return PointerIcon.getSystemIcon(context, type);
195         }
196 
create(Bitmap bitmap, float hotSpotX, float hotSpotY)197         static PointerIcon create(Bitmap bitmap, float hotSpotX, float hotSpotY) {
198             return PointerIcon.create(bitmap, hotSpotX, hotSpotY);
199         }
200 
load(Resources resources, int resourceId)201         static PointerIcon load(Resources resources, int resourceId) {
202             return PointerIcon.load(resources, resourceId);
203         }
204     }
205 }
206