• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "frameworks/core/components/common/properties/decoration.h"
26 
27 // avoid windows build error about macro defined in wincon.h
28 #ifdef DOUBLE_CLICK
29 #undef DOUBLE_CLICK
30 #endif
31 
32 namespace OHOS::Ace::NG {
33 
34 using OnAccessibilityCallback = std::function<void()>;
35 
36 enum class CaretUpdateType {
37     PRESSED,
38     LONG_PRESSED,
39     ICON_PRESSED,
40     DEL,
41     EVENT,
42     HANDLE_MOVE,
43     HANDLE_MOVE_DONE,
44     INPUT,
45     NONE,
46     RIGHT_CLICK,
47     VISIBLE_PASSWORD_ICON,
48     DOUBLE_CLICK
49 };
50 /**
51  * Stands for selection indexes
52  * We use base/destination to indicate the start/end position because of uncertain direction.
53  */
54 struct HandleInfo {
55     int32_t index = 0;
56     RectF rect;
57 
AddRectYHandleInfo58     void AddRectY(float deltaY)
59     {
60         auto newOffset = rect.GetOffset();
61         newOffset.AddY(deltaY);
62         rect.SetOffset(newOffset);
63     }
64 
AddRectXHandleInfo65     void AddRectX(float deltaX)
66     {
67         auto newOffset = rect.GetOffset();
68         newOffset.AddX(deltaX);
69         rect.SetOffset(newOffset);
70     }
71 };
72 struct TextSelector {
73     TextSelector() = default;
TextSelectorTextSelector74     TextSelector(int32_t base, int32_t destination) : baseOffset(base), destinationOffset(destination) {}
75 
SetOnAccessibilityTextSelector76     void SetOnAccessibility(OnAccessibilityCallback&& onAccessibilityCallback)
77     {
78         if (onAccessibilityCallback) {
79             onAccessibilityCallback_ = std::move(onAccessibilityCallback);
80         }
81     }
82 
FireAccessibilityCallbackTextSelector83     void FireAccessibilityCallback() const
84     {
85         if (onAccessibilityCallback_) {
86             onAccessibilityCallback_();
87         }
88     }
89 
UpdateTextSelector90     void Update(int32_t base, int32_t destination)
91     {
92         if (base == baseOffset && destination == destinationOffset) {
93             return;
94         }
95         bool isChanged = baseOffset != destinationOffset || base != destination;
96         baseOffset = base;
97         if (baseOffset >= 0) {
98             lastValidStart = baseOffset;
99         }
100         destinationOffset = destination;
101         if (isChanged) {
102             FireAccessibilityCallback();
103         }
104     }
105 
106     // Usually called when none is selected.
UpdateTextSelector107     void Update(int32_t both)
108     {
109         if ((baseOffset != both) || (destinationOffset != both)) {
110             if (baseOffset != destinationOffset) {
111                 FireAccessibilityCallback();
112             }
113         }
114         baseOffset = both;
115         destinationOffset = both;
116         if (baseOffset >= 0) {
117             lastValidStart = baseOffset;
118         }
119     }
120 
ReverseTextSelectorTextSelector121     void ReverseTextSelector()
122     {
123         if (baseOffset > destinationOffset) {
124             Update(destinationOffset, baseOffset);
125         }
126     }
127 
128     bool operator==(const TextSelector& other) const
129     {
130         return baseOffset == other.baseOffset && destinationOffset == other.destinationOffset;
131     }
132 
133     bool operator!=(const TextSelector& other) const
134     {
135         return !operator==(other);
136     }
137 
GetTextStartTextSelector138     inline int32_t GetTextStart() const
139     {
140         return std::min(baseOffset, destinationOffset);
141     }
142 
GetTextEndTextSelector143     inline int32_t GetTextEnd() const
144     {
145         return std::max(baseOffset, destinationOffset);
146     }
147 
GetStartTextSelector148     inline int32_t GetStart() const
149     {
150         return baseOffset;
151     }
152 
GetEndTextSelector153     inline int32_t GetEnd() const
154     {
155         return destinationOffset;
156     }
157 
IsValidTextSelector158     inline bool IsValid() const
159     {
160         return baseOffset > -1 && destinationOffset > -1;
161     }
162 
SelectNothingTextSelector163     inline bool SelectNothing() const
164     {
165         return !IsValid() || baseOffset == destinationOffset;
166     }
167 
MoveSelectionLeftTextSelector168     bool MoveSelectionLeft()
169     {
170         destinationOffset = std::max(0, destinationOffset - 1);
171         return destinationOffset == baseOffset;
172     }
173 
MoveSelectionRightTextSelector174     bool MoveSelectionRight()
175     {
176         destinationOffset = std::min(charCount, destinationOffset + 1);
177         return destinationOffset == baseOffset;
178     }
179 
GetSelectHeightTextSelector180     double GetSelectHeight() const
181     {
182         return std::max(firstHandle.Height(), secondHandle.Height());
183     }
184 
StartEqualToDestTextSelector185     bool StartEqualToDest() const
186     {
187         return baseOffset == destinationOffset;
188     }
189 
StartGreaterDestTextSelector190     bool StartGreaterDest() const
191     {
192         return baseOffset > destinationOffset;
193     }
194 
ContainsRangeTextSelector195     bool ContainsRange(const std::pair<int32_t, int32_t>& range) const
196     {
197         return IsValid() && GetTextStart() <= range.first && range.second <= GetTextEnd();
198     }
199 
ToStringTextSelector200     std::string ToString()
201     {
202         std::string result;
203         result.append("baseOffset: ");
204         result.append(std::to_string(baseOffset));
205         result.append(", selectionBaseOffset: ");
206         result.append(selectionBaseOffset.ToString());
207         result.append(", destinationOffset: ");
208         result.append(std::to_string(destinationOffset));
209         result.append(", selectionDestinationOffset: ");
210         result.append(selectionDestinationOffset.ToString());
211         result.append(", firstHandle: ");
212         result.append(firstHandle.ToString());
213         result.append(", secondHandle: ");
214         result.append(secondHandle.ToString());
215         result.append(", firstHandleOffset_: ");
216         result.append(firstHandleOffset_.ToString());
217         result.append(", secondHandleOffset_: ");
218         result.append(secondHandleOffset_.ToString());
219         return result;
220     }
221 
222     // May larger than, smaller than or equal to destinationOffset.
223     int32_t baseOffset = -1;
224     OffsetF selectionBaseOffset;
225 
226     // When paints caret, this is where the caret position is.
227     int32_t destinationOffset = -1;
228     OffsetF selectionDestinationOffset;
229 
230     int32_t charCount = 0;
231     RectF firstHandle;
232     RectF secondHandle;
233     OffsetF firstHandleOffset_;
234     OffsetF secondHandleOffset_;
235     OnAccessibilityCallback onAccessibilityCallback_;
236     int32_t lastValidStart = 0;
237 };
238 
239 enum class TextSpanType : int32_t {
240     TEXT = 0,
241     IMAGE,
242     MIXED,
243     BUILDER,
244     NONE,
245 };
246 
247 enum class TextResponseType : int32_t {
248     RIGHT_CLICK = 0,
249     LONG_PRESS,
250     SELECTED_BY_MOUSE,
251     NONE,
252 };
253 
254 enum class SelectionMenuType : int32_t {
255     SELECTION_MENU = 0,
256     PREVIEW_MENU = 1,
257 };
258 
259 struct PreviewMenuOptions {
260     HapticFeedbackMode hapticFeedbackMode = HapticFeedbackMode::DISABLED;
261 };
262 
263 struct SelectMenuParam {
264     std::function<void(int32_t, int32_t)> onAppear;
265     std::function<void()> onDisappear;
266     std::function<void(int32_t, int32_t)> onMenuShow;
267     std::function<void(int32_t, int32_t)> onMenuHide;
268     bool isValid = true;
269     PreviewMenuOptions previewMenuOptions;
270 };
271 
272 struct SelectionMenuParams {
273     TextSpanType type;
274     std::function<void()> buildFunc;
275     std::function<void(int32_t, int32_t)> onAppear;
276     std::function<void()> onDisappear;
277     TextResponseType responseType;
278     std::function<void(int32_t, int32_t)> onMenuShow;
279     std::function<void(int32_t, int32_t)> onMenuHide;
280     bool isValid = true;
281 
SelectionMenuParamsSelectionMenuParams282     SelectionMenuParams(TextSpanType _type, std::function<void()> _buildFunc,
283         std::function<void(int32_t, int32_t)> _onAppear, std::function<void()> _onDisappear,
284         TextResponseType _responseType)
285         : type(_type), buildFunc(_buildFunc), onAppear(_onAppear), onDisappear(_onDisappear),
286           responseType(_responseType)
287     {}
288 };
289 
290 struct TextSpanTypeMapper {
GetTextSpanTypeFromJsTypeTextSpanTypeMapper291     static bool GetTextSpanTypeFromJsType(int32_t spanTypeId, NG::TextSpanType& spanType)
292     {
293         std::unordered_map<int32_t, NG::TextSpanType> spanTypeMap = {
294             { 0, NG::TextSpanType::TEXT },
295             { 1, NG::TextSpanType::IMAGE },
296             { 2, NG::TextSpanType::MIXED },
297             { 3, NG::TextSpanType::NONE }
298         };
299         if (spanTypeMap.find(spanTypeId) != spanTypeMap.end()) {
300             spanType = spanTypeMap[spanTypeId];
301             return true;
302         }
303         spanType = static_cast<NG::TextSpanType>(spanTypeId);
304         return false;
305     }
306 
GetJsSpanTypeTextSpanTypeMapper307     static int32_t GetJsSpanType(const NG::TextSpanType& spanType, bool isValid)
308     {
309         std::unordered_map<NG::TextSpanType, int32_t> spanTypeMap = {
310             { NG::TextSpanType::TEXT, 0 },
311             { NG::TextSpanType::IMAGE, 1 },
312             { NG::TextSpanType::MIXED, 2 },
313             { NG::TextSpanType::NONE, 3 }
314         };
315         if (isValid) {
316             return spanTypeMap[spanType];
317         }
318         return static_cast<int32_t>(spanType);
319     }
320 };
321 
322 } // namespace OHOS::Ace::NG
323 
324 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_FIELD_TEXT_SELECTOR_H
325