1 /*
2  * Copyright (C) 2021 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 android.view.inputmethod;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 
22 import java.util.Objects;
23 
24 /**
25  * An immutable data snapshot of text editing state.
26  */
27 public final class TextSnapshot {
28     @NonNull
29     private final SurroundingText mSurroundingText;
30     @IntRange(from = -1)
31     private final int mCompositionStart;
32     @IntRange(from = -1)
33     private final int mCompositionEnd;
34     private final int mCursorCapsMode;
35 
36     /**
37      * Creates a new instance of {@link TextSnapshot}
38      *
39      * @param surroundingText {@link SurroundingText} of the current edit field.
40      * @param compositionStart The start index of the composing text.
41      *                         {@code -1} if there is no composing text.
42      * @param compositionEnd The end index of the composing text.
43      *                       {@code -1} if there is no composing text.
44      * @param cursorCapsMode The capitalization mode of the first character being edited in the
45      *                       text.  See {@link EditorInfo#initialCapsMode}.
46      * @throws NullPointerException if {@code surroundingText} is {@code null}.
47      * @throws IllegalArgumentException if {@code compositionStart} and/or {@code compositionEnd}
48      *                                  is less than {@code -1}.
49      */
TextSnapshot(@onNull SurroundingText surroundingText, @IntRange(from = -1) int compositionStart, @IntRange(from = -1) int compositionEnd, int cursorCapsMode)50     public TextSnapshot(@NonNull SurroundingText surroundingText,
51             @IntRange(from = -1) int compositionStart, @IntRange(from = -1) int compositionEnd,
52             int cursorCapsMode) {
53         Objects.requireNonNull(surroundingText);
54         mSurroundingText = surroundingText;
55         if (compositionStart < -1) {
56             throw new IllegalArgumentException("compositionStart must be -1 or higher but was "
57                     + compositionStart);
58         }
59         if (compositionEnd < -1) {
60             throw new IllegalArgumentException("compositionEnd must be -1 or higher but was "
61                     + compositionEnd);
62         }
63         if (compositionStart == -1 && compositionEnd != -1) {
64             throw new IllegalArgumentException("compositionEnd must be -1 if compositionStart is "
65                     + "-1 but was " + compositionEnd);
66         }
67         if (compositionStart != -1 && compositionEnd == -1) {
68             throw new IllegalArgumentException("compositionStart must be -1 if compositionEnd is "
69                     + "-1 but was " + compositionStart);
70         }
71         if (compositionStart > compositionEnd) {
72             throw new IllegalArgumentException("compositionStart=" + compositionStart + " must be"
73                     + " equal to or greater than compositionEnd=" + compositionEnd);
74         }
75         mCompositionStart = compositionStart;
76         mCompositionEnd = compositionEnd;
77         mCursorCapsMode = cursorCapsMode;
78     }
79 
80     /**
81      * @return {@link SurroundingText} of the current edit field.
82      */
83     @NonNull
getSurroundingText()84     public SurroundingText getSurroundingText() {
85         return mSurroundingText;
86     }
87 
88     /**
89      * @return The start index of the selection range. {@code -1} if it is not available.
90      */
91     @IntRange(from = -1)
getSelectionStart()92     public int getSelectionStart() {
93         if (mSurroundingText.getOffset() < 0) {
94             return -1;
95         }
96         return mSurroundingText.getSelectionStart() + mSurroundingText.getOffset();
97     }
98 
99     /**
100      * @return The end index of the selection range. {@code -1} if it is not available.
101      */
102     @IntRange(from = -1)
getSelectionEnd()103     public int getSelectionEnd() {
104         if (mSurroundingText.getOffset() < 0) {
105             return -1;
106         }
107         return mSurroundingText.getSelectionEnd() + mSurroundingText.getOffset();
108     }
109 
110     /**
111      * @return The end index of the composing text. {@code -1} if there is no composing text.
112      */
113     @IntRange(from = -1)
getCompositionStart()114     public int getCompositionStart() {
115         return mCompositionStart;
116     }
117 
118     /**
119      * @return The end index of the composing text. {@code -1} if there is no composing text.
120      */
121     @IntRange(from = -1)
getCompositionEnd()122     public int getCompositionEnd() {
123         return mCompositionEnd;
124     }
125 
126     /**
127      * The capitalization mode of the first character being edited in the text.
128      *
129      * <p>Values may be any combination of the following values:</p>
130      * <ul>
131      *     <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS}</li>
132      *     <li>{@link android.text.TextUtils#CAP_MODE_WORDS TextUtils.CAP_MODE_WORDS}</li>
133      *     <li>{@link android.text.TextUtils#CAP_MODE_SENTENCES TextUtils.CAP_MODE_SENTENCES}</li>
134      * </ul>
135      *
136      * <p>You should generally just take a non-zero value to mean "start out in caps mode" though.
137      * </p>
138      * @see EditorInfo#initialCapsMode
139      */
getCursorCapsMode()140     public int getCursorCapsMode() {
141         return mCursorCapsMode;
142     }
143 }
144 
145