1 /*
2  * Copyright (C) 2022 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.NonNull;
20 import android.annotation.Nullable;
21 import android.graphics.PointF;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.util.Objects;
26 
27 /**
28  * A subclass of {@link HandwritingGesture} for deleting or inserting whitespace in text. If the
29  * gesture is drawn over whitespace, then the whitespace will be deleted. Otherwise, a space will be
30  * inserted.
31  */
32 public final class JoinOrSplitGesture extends HandwritingGesture implements Parcelable {
33 
34     private final PointF mPoint;
35 
JoinOrSplitGesture(PointF point, String fallbackText)36     private JoinOrSplitGesture(PointF point, String fallbackText) {
37         mType = GESTURE_TYPE_JOIN_OR_SPLIT;
38         mPoint = point;
39         mFallbackText = fallbackText;
40     }
41 
JoinOrSplitGesture(@onNull Parcel source)42     private JoinOrSplitGesture(@NonNull Parcel source) {
43         mType = GESTURE_TYPE_JOIN_OR_SPLIT;
44         mPoint = source.readTypedObject(PointF.CREATOR);
45         mFallbackText = source.readString8();
46     }
47 
48     /**
49      * Returns the gesture point in screen coordinates set with {@link Builder#setJoinOrSplitPoint}.
50      */
51     @NonNull
getJoinOrSplitPoint()52     public PointF getJoinOrSplitPoint() {
53         return mPoint;
54     }
55 
56     /** Builder for {@link JoinOrSplitGesture}. This class is not designed to be thread-safe. */
57     public static final class Builder {
58         private PointF mPoint;
59         private String mFallbackText;
60 
61         /**
62          * Sets the point to apply the join or split operation in screen coordinates.
63          *
64          * <p>If the text cursor position closest to the point is inside or on the boundary of
65          * whitespace, then the whitespace will be deleted, joining the text on either side of the
66          * whitespace. If there are multiple consecutive whitespace characters, then the entire
67          * whitespace block will be deleted.
68          *
69          * <p>Otherwise, if the text cursor position closest to the point is not touching
70          * whitespace, then a space will be inserted at that position.
71          */
72         @NonNull
setJoinOrSplitPoint(@onNull PointF point)73         public Builder setJoinOrSplitPoint(@NonNull PointF point) {
74             mPoint = point;
75             return this;
76         }
77 
78         /**
79          * Sets fallback text that will be committed at current cursor position if there is no
80          * applicable text beneath the gesture point.
81          */
82         @NonNull
setFallbackText(@ullable String fallbackText)83         public Builder setFallbackText(@Nullable String fallbackText) {
84             mFallbackText = fallbackText;
85             return this;
86         }
87 
88         /**
89          * @return {@link JoinOrSplitGesture} using parameters in this {@link Builder}.
90          * @throws IllegalArgumentException if one or more positional parameters are not specified.
91          */
92         @NonNull
build()93         public JoinOrSplitGesture build() {
94             if (mPoint == null) {
95                 throw new IllegalArgumentException("Point must be set.");
96             }
97             return new JoinOrSplitGesture(mPoint, mFallbackText);
98         }
99     }
100 
101     /** Used to make this class parcelable. */
102     @NonNull
103     public static final Parcelable.Creator<JoinOrSplitGesture> CREATOR =
104             new Parcelable.Creator<JoinOrSplitGesture>() {
105                 @Override
106                 public JoinOrSplitGesture createFromParcel(Parcel source) {
107                     return new JoinOrSplitGesture(source);
108                 }
109 
110                 @Override
111                 public JoinOrSplitGesture[] newArray(int size) {
112                     return new JoinOrSplitGesture[size];
113                 }
114             };
115 
116     @Override
hashCode()117     public int hashCode() {
118         return Objects.hash(mPoint, mFallbackText);
119     }
120 
121     @Override
equals(Object o)122     public boolean equals(Object o) {
123         if (!(o instanceof JoinOrSplitGesture)) return false;
124         JoinOrSplitGesture that = (JoinOrSplitGesture) o;
125         return Objects.equals(mPoint, that.mPoint)
126                 && Objects.equals(mFallbackText, that.mFallbackText);
127     }
128 
129     @Override
describeContents()130     public int describeContents() {
131         return 0;
132     }
133 
134     /**
135      * Used to package this object into a {@link Parcel}.
136      *
137      * @param dest {@link Parcel} to be written
138      * @param flags flags used for parceling
139      */
140     @Override
writeToParcel(@onNull Parcel dest, int flags)141     public void writeToParcel(@NonNull Parcel dest, int flags) {
142         dest.writeTypedObject(mPoint, flags);
143         dest.writeString8(mFallbackText);
144     }
145 }
146