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.accessibility;
18 
19 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
20 
21 import android.os.Bundle;
22 import android.view.View;
23 
24 import androidx.annotation.RestrictTo;
25 
26 import org.jspecify.annotations.NonNull;
27 import org.jspecify.annotations.Nullable;
28 
29 /**
30  * Functional interface used to create a custom accessibility action.
31  */
32 public interface AccessibilityViewCommand {
33     /**
34      * Performs the action.
35      *
36      * @return {@code true} if the action was handled, {@code false} otherwise
37      *
38      * @param view The view to act on
39      * @param arguments Optional action arguments
40      */
perform(@onNull View view, AccessibilityViewCommand.@Nullable CommandArguments arguments)41     boolean perform(@NonNull View view,
42             AccessibilityViewCommand.@Nullable CommandArguments arguments);
43 
44     /**
45      * Object containing arguments passed into an {@link AccessibilityViewCommand}
46      */
47     abstract class CommandArguments {
48         Bundle mBundle;
49 
50         /**
51          */
52         @RestrictTo(LIBRARY_GROUP_PREFIX)
setBundle(@ullable Bundle bundle)53         public void setBundle(@Nullable Bundle bundle) {
54             mBundle = bundle;
55         }
56     }
57 
58     /**
59      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
60      * #ACTION_NEXT_AT_MOVEMENT_GRANULARITY}
61      * and {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
62      * #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
63      */
64     final class MoveAtGranularityArguments extends CommandArguments {
65 
66         /**
67          * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_CHARACTER
68          *  AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_CHARACTER
69          * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_WORD
70          *  AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_WORD
71          * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_LINE
72          *  AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE
73          * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PARAGRAPH
74          *  AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PARAGRAPH
75          * @see AccessibilityNodeInfoCompat#MOVEMENT_GRANULARITY_PAGE
76          *  AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_PAGE
77          * @return Movement granularity to be used when traversing the node text.
78          */
getGranularity()79         public int getGranularity() {
80             return mBundle.getInt(
81                     AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
82         }
83 
84         /**
85          * @return Whether when moving at granularity to extend the selection or to move it.
86          */
getExtendSelection()87         public boolean getExtendSelection() {
88             return mBundle.getBoolean(
89                     AccessibilityNodeInfoCompat.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
90         }
91     }
92 
93     /**
94      * Arguments for {@link AccessibilityNodeInfoCompat#ACTION_NEXT_HTML_ELEMENT}
95      * and {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
96      * #ACTION_PREVIOUS_HTML_ELEMENT}
97      */
98     final class MoveHtmlArguments extends CommandArguments {
99 
100         /**
101          * @return HTML element type, for example BUTTON, INPUT, TABLE, etc.
102          */
getHTMLElement()103         public @Nullable String getHTMLElement() {
104             return mBundle.getString(
105                     AccessibilityNodeInfoCompat.ACTION_ARGUMENT_HTML_ELEMENT_STRING);
106         }
107     }
108 
109     /**
110      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
111      * #ACTION_SET_SELECTION}
112      */
113     final class SetSelectionArguments extends CommandArguments {
114 
115         /**
116          * @return Selection start.
117          */
getStart()118         public int getStart() {
119             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_START_INT);
120         }
121 
122         /**
123          * @return Selection End.
124          */
getEnd()125         public int getEnd() {
126             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SELECTION_END_INT);
127         }
128     }
129 
130     /**
131      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat#ACTION_SET_TEXT}
132      */
133     final class SetTextArguments extends CommandArguments {
134 
135         /**
136          * @return The text content to set.
137          */
getText()138         public @Nullable CharSequence getText() {
139             return mBundle.getCharSequence(
140                     AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE);
141         }
142     }
143 
144     /**
145      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
146      * #ACTION_SCROLL_TO_POSITION}
147      */
148     final class ScrollToPositionArguments extends CommandArguments {
149 
150         /**
151          * @return The collection row to make visible on screen.
152          */
getRow()153         public int getRow() {
154             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_ROW_INT);
155         }
156 
157         /**
158          * @return The collection column to make visible on screen.
159          */
getColumn()160         public int getColumn() {
161             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT);
162         }
163     }
164 
165     /**
166      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
167      * #ACTION_SET_PROGRESS}
168      */
169     final class SetProgressArguments extends CommandArguments {
170 
171         /**
172          * @return The progress value to set.
173          */
getProgress()174         public float getProgress() {
175             return mBundle.getFloat(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE);
176         }
177     }
178 
179     /**
180      * Arguments for {@link AccessibilityNodeInfoCompat.AccessibilityActionCompat
181      * #ACTION_MOVE_WINDOW}
182      */
183     final class MoveWindowArguments extends CommandArguments {
184 
185         /**
186          * @return The x coordinate to which to move a window.
187          */
getX()188         public int getX() {
189             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVE_WINDOW_X);
190         }
191 
192         /**
193          * @return The y coordinate to which to move a window.
194          */
getY()195         public int getY() {
196             return mBundle.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_MOVE_WINDOW_Y);
197         }
198     }
199 }
200