1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H
18 
19 #include <cstdint>
20 #include <string>
21 #include <functional>
22 
23 #include "base/geometry/ng/offset_t.h"
24 #include "base/geometry/ng/rect_t.h"
25 
26 // avoid windows build error about macro defined in wincon.h
27 #ifdef DOUBLE_CLICK
28 #undef DOUBLE_CLICK
29 #endif
30 
31 namespace OHOS::Ace::NG {
32 
33 using OnAccessibilityCallback = std::function<void()>;
34 
35 enum class CaretUpdateType {
36     PRESSED,
37     LONG_PRESSED,
38     ICON_PRESSED,
39     DEL,
40     EVENT,
41     HANDLE_MOVE,
42     HANDLE_MOVE_DONE,
43     INPUT,
44     NONE,
45     RIGHT_CLICK,
46     VISIBLE_PASSWORD_ICON,
47     DOUBLE_CLICK
48 };
49 /**
50  * Stands for selection indexes
51  * We use base/destination to indicate the start/end position because of uncertain direction.
52  */
53 struct HandleInfo {
54     int32_t index = 0;
55     RectF rect;
56 
AddRectYHandleInfo57     void AddRectY(float deltaY)
58     {
59         auto newOffset = rect.GetOffset();
60         newOffset.AddY(deltaY);
61         rect.SetOffset(newOffset);
62     }
63 
AddRectXHandleInfo64     void AddRectX(float deltaX)
65     {
66         auto newOffset = rect.GetOffset();
67         newOffset.AddX(deltaX);
68         rect.SetOffset(newOffset);
69     }
70 };
71 struct TextSelector {
72     TextSelector() = default;
TextSelectorTextSelector73     TextSelector(int32_t base, int32_t destination) : baseOffset(base), destinationOffset(destination) {}
74 
SetOnAccessibilityTextSelector75     void SetOnAccessibility(OnAccessibilityCallback&& onAccessibilityCallback)
76     {
77         if (onAccessibilityCallback) {
78             onAccessibilityCallback_ = std::move(onAccessibilityCallback);
79         }
80     }
81 
FireAccessibilityCallbackTextSelector82     void FireAccessibilityCallback() const
83     {
84         if (onAccessibilityCallback_) {
85             onAccessibilityCallback_();
86         }
87     }
88 
UpdateTextSelector89     void Update(int32_t base, int32_t destination)
90     {
91         if (base == baseOffset && destination == destinationOffset) {
92             return;
93         }
94         bool isChanged = baseOffset != destinationOffset || base != destination;
95         baseOffset = base;
96         destinationOffset = destination;
97         if (isChanged) {
98             FireAccessibilityCallback();
99         }
100     }
101 
102     // Usually called when none is selected.
UpdateTextSelector103     void Update(int32_t both)
104     {
105         if ((baseOffset != both) || (destinationOffset != both)) {
106             if (baseOffset != destinationOffset) {
107                 FireAccessibilityCallback();
108             }
109         }
110         baseOffset = both;
111         destinationOffset = both;
112     }
113 
ReverseTextSelectorTextSelector114     void ReverseTextSelector()
115     {
116         if (baseOffset > destinationOffset) {
117             Update(destinationOffset, baseOffset);
118         }
119     }
120 
121     bool operator==(const TextSelector& other) const
122     {
123         return baseOffset == other.baseOffset && destinationOffset == other.destinationOffset;
124     }
125 
126     bool operator!=(const TextSelector& other) const
127     {
128         return !operator==(other);
129     }
130 
GetTextStartTextSelector131     inline int32_t GetTextStart() const
132     {
133         return std::min(baseOffset, destinationOffset);
134     }
135 
GetTextEndTextSelector136     inline int32_t GetTextEnd() const
137     {
138         return std::max(baseOffset, destinationOffset);
139     }
140 
GetStartTextSelector141     inline int32_t GetStart() const
142     {
143         return baseOffset;
144     }
145 
GetEndTextSelector146     inline int32_t GetEnd() const
147     {
148         return destinationOffset;
149     }
150 
IsValidTextSelector151     inline bool IsValid() const
152     {
153         return baseOffset > -1 && destinationOffset > -1;
154     }
155 
SelectNothingTextSelector156     inline bool SelectNothing() const
157     {
158         return !IsValid() || baseOffset == destinationOffset;
159     }
160 
MoveSelectionLeftTextSelector161     bool MoveSelectionLeft()
162     {
163         destinationOffset = std::max(0, destinationOffset - 1);
164         return destinationOffset == baseOffset;
165     }
166 
MoveSelectionRightTextSelector167     bool MoveSelectionRight()
168     {
169         destinationOffset = std::min(charCount, destinationOffset + 1);
170         return destinationOffset == baseOffset;
171     }
172 
GetSelectHeightTextSelector173     double GetSelectHeight() const
174     {
175         return std::max(firstHandle.Height(), secondHandle.Height());
176     }
177 
StartEqualToDestTextSelector178     bool StartEqualToDest() const
179     {
180         return baseOffset == destinationOffset;
181     }
182 
StartGreaterDestTextSelector183     bool StartGreaterDest() const
184     {
185         return baseOffset > destinationOffset;
186     }
187 
ToStringTextSelector188     std::string ToString()
189     {
190         std::string result;
191         result.append("baseOffset: ");
192         result.append(std::to_string(baseOffset));
193         result.append(", selectionBaseOffset: ");
194         result.append(selectionBaseOffset.ToString());
195         result.append(", destinationOffset: ");
196         result.append(std::to_string(destinationOffset));
197         result.append(", selectionDestinationOffset: ");
198         result.append(selectionDestinationOffset.ToString());
199         result.append(", firstHandle: ");
200         result.append(firstHandle.ToString());
201         result.append(", secondHandle: ");
202         result.append(secondHandle.ToString());
203         result.append(", firstHandleOffset_: ");
204         result.append(firstHandleOffset_.ToString());
205         result.append(", secondHandleOffset_: ");
206         result.append(secondHandleOffset_.ToString());
207         return result;
208     }
209 
210     // May larger than, smaller than or equal to destinationOffset.
211     int32_t baseOffset = -1;
212     OffsetF selectionBaseOffset;
213 
214     // When paints caret, this is where the caret position is.
215     int32_t destinationOffset = -1;
216     OffsetF selectionDestinationOffset;
217 
218     int32_t charCount = 0;
219     RectF firstHandle;
220     RectF secondHandle;
221     OffsetF firstHandleOffset_;
222     OffsetF secondHandleOffset_;
223     OnAccessibilityCallback onAccessibilityCallback_;
224 };
225 
226 enum class TextSpanType : int32_t {
227     TEXT = 0,
228     IMAGE,
229     MIXED,
230     BUILDER,
231     NONE,
232 };
233 
234 enum class TextResponseType : int32_t {
235     RIGHT_CLICK = 0,
236     LONG_PRESS,
237     SELECTED_BY_MOUSE,
238     NONE,
239 };
240 
241 enum class SelectionMenuType : int32_t {
242     SELECTION_MENU = 0,
243     PREVIEW_MENU = 1,
244 };
245 
246 struct SelectMenuParam {
247     std::function<void(int32_t, int32_t)> onAppear;
248     std::function<void()> onDisappear;
249 };
250 
251 struct SelectionMenuParams {
252     TextSpanType type;
253     std::function<void()> buildFunc;
254     std::function<void(int32_t, int32_t)> onAppear;
255     std::function<void()> onDisappear;
256     TextResponseType responseType;
257 
SelectionMenuParamsSelectionMenuParams258     SelectionMenuParams(TextSpanType _type, std::function<void()> _buildFunc,
259         std::function<void(int32_t, int32_t)> _onAppear, std::function<void()> _onDisappear,
260         TextResponseType _responseType)
261         : type(_type), buildFunc(_buildFunc), onAppear(_onAppear), onDisappear(_onDisappear),
262           responseType(_responseType)
263     {}
264 };
265 
266 } // namespace OHOS::Ace::NG
267 
268 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H
269