1 /*
2 * Copyright (c) 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_TEXT_BASE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_TEXT_BASE_H
18
19 #include "base/memory/ace_type.h"
20 #include "base/memory/referenced.h"
21 #include "core/common/clipboard/clipboard.h"
22 #include "core/components_ng/manager/select_overlay/select_overlay_client.h"
23 #include "core/components_ng/pattern/text_field/text_selector.h"
24 #include "core/components_ng/render/paragraph.h"
25
26 namespace OHOS::Ace::NG {
27
28 enum class MouseStatus { PRESSED, RELEASED, MOVE, NONE };
29 enum {
30 ACTION_SELECT_ALL, // Smallest code unit.
31 ACTION_UNDO,
32 ACTION_REDO,
33 ACTION_CUT,
34 ACTION_COPY,
35 ACTION_PASTE,
36 ACTION_SHARE,
37 ACTION_PASTE_AS_PLAIN_TEXT,
38 ACTION_REPLACE,
39 ACTION_ASSIST,
40 ACTION_AUTOFILL,
41 };
42
43 struct HandleMoveStatus {
44 bool isFirsthandle = false;
45 int32_t position = -1;
46 OffsetF handleOffset;
47
ResetHandleMoveStatus48 void Reset()
49 {
50 isFirsthandle = false;
51 position = -1;
52 }
53
IsValidHandleMoveStatus54 bool IsValid()
55 {
56 return position >= 0;
57 }
58 };
59
60 template<typename T>
GetTextCaretMetrics(RefPtr<FrameNode> & targetNode,CaretMetricsF & caretMetrics)61 void GetTextCaretMetrics(RefPtr<FrameNode>& targetNode, CaretMetricsF& caretMetrics)
62 {
63 CHECK_NULL_VOID(targetNode);
64 if (targetNode->GetTag() == V2::SEARCH_ETS_TAG) {
65 auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(targetNode->GetChildren().front());
66 CHECK_NULL_VOID(textFieldFrameNode);
67 auto textPattern = textFieldFrameNode->GetPattern<T>();
68 CHECK_NULL_VOID(textPattern);
69 textPattern->GetCaretMetrics(caretMetrics);
70 } else {
71 auto textPattern = targetNode->GetPattern<T>();
72 CHECK_NULL_VOID(textPattern);
73 textPattern->GetCaretMetrics(caretMetrics);
74 }
75 }
76
77 namespace TextChangeType {
78 const std::string ADD = "addText";
79 const std::string REMOVE = "removeText";
80 };
81
82 class TextGestureSelector : public virtual AceType {
83 DECLARE_ACE_TYPE(TextGestureSelector, AceType);
84
85 public:
StartGestureSelection(int32_t start,int32_t end,const Offset & startOffset)86 virtual void StartGestureSelection(int32_t start, int32_t end, const Offset& startOffset)
87 {
88 start_ = start;
89 end_ = end;
90 isStarted_ = start_ <= end_;
91 startOffset_ = startOffset;
92 }
93
CancelGestureSelection()94 void CancelGestureSelection()
95 {
96 DoTextSelectionTouchCancel();
97 ResetGestureSelection();
98 }
99
EndGestureSelection(const TouchLocationInfo & locationInfo)100 void EndGestureSelection(const TouchLocationInfo& locationInfo)
101 {
102 OnTextGestureSelectionEnd(locationInfo);
103 ResetGestureSelection();
104 }
105
106 void DoGestureSelection(const TouchEventInfo& info);
107
108 protected:
GetTouchIndex(const OffsetF & offset)109 virtual int32_t GetTouchIndex(const OffsetF& offset)
110 {
111 return -1;
112 }
OnTextGestureSelectionUpdate(int32_t start,int32_t end,const TouchEventInfo & info)113 virtual void OnTextGestureSelectionUpdate(int32_t start, int32_t end, const TouchEventInfo& info) {}
OnTextGestureSelectionEnd(const TouchLocationInfo & locationInfo)114 virtual void OnTextGestureSelectionEnd(const TouchLocationInfo& locationInfo) {}
DoTextSelectionTouchCancel()115 virtual void DoTextSelectionTouchCancel() {}
GetSelectingFingerId()116 int32_t GetSelectingFingerId()
117 {
118 return selectingFingerId_;
119 }
120
IsGestureSelectingText()121 bool IsGestureSelectingText()
122 {
123 return isSelecting_;
124 }
125 private:
ResetGestureSelection()126 void ResetGestureSelection()
127 {
128 start_ = -1;
129 end_ = -1;
130 isStarted_ = false;
131 startOffset_.Reset();
132 isSelecting_ = false;
133 selectingFingerId_ = -1;
134 }
135 void DoTextSelectionTouchMove(const TouchEventInfo& info);
136 int32_t start_ = -1;
137 int32_t end_ = -1;
138 bool isStarted_ = false;
139 bool isSelecting_ = false;
140 Dimension minMoveDistance_ = 5.0_vp;
141 Offset startOffset_;
142 int32_t selectingFingerId_ = -1;
143 };
144
145 class TextBase : public SelectOverlayClient {
146 DECLARE_ACE_TYPE(TextBase, SelectOverlayClient);
147
148 public:
149 TextBase() = default;
150 ~TextBase() override = default;
151
GetContentOffset()152 virtual OffsetF GetContentOffset()
153 {
154 return OffsetF(0, 0);
155 }
156
OnBackPressed()157 virtual bool OnBackPressed()
158 {
159 return false;
160 }
161
IsSelected()162 virtual bool IsSelected() const
163 {
164 return textSelector_.IsValid() && !textSelector_.StartEqualToDest();
165 }
166
CanAIEntityDrag()167 virtual bool CanAIEntityDrag()
168 {
169 return false;
170 }
171
GetMouseStatus()172 MouseStatus GetMouseStatus() const
173 {
174 return mouseStatus_;
175 }
176
177 // The methods that need to be implemented for input class components
GetCaretRect()178 virtual RectF GetCaretRect() const
179 {
180 return { 0, 0, 0, 0 };
181 }
182
ScrollToSafeArea()183 virtual void ScrollToSafeArea() const {}
184
GetCaretMetrics(CaretMetricsF & caretCaretMetric)185 virtual void GetCaretMetrics(CaretMetricsF& caretCaretMetric) {}
186
OnVirtualKeyboardAreaChanged()187 virtual void OnVirtualKeyboardAreaChanged() {}
188
GetClipboard()189 virtual RefPtr<Clipboard> GetClipboard()
190 {
191 return nullptr;
192 }
193
GetContentRect()194 const RectF& GetContentRect() const
195 {
196 return contentRect_;
197 }
198
GetPaintContentRect()199 virtual RectF GetPaintContentRect()
200 {
201 return contentRect_;
202 }
203
GetContentWideTextLength()204 virtual int32_t GetContentWideTextLength()
205 {
206 return 0;
207 }
208
GetCaretIndex()209 virtual int32_t GetCaretIndex() const
210 {
211 return 0;
212 }
213
GetCaretOffset()214 virtual OffsetF GetCaretOffset() const
215 {
216 return OffsetF();
217 }
218
GetTextPaintOffset()219 virtual OffsetF GetTextPaintOffset() const
220 {
221 return OffsetF();
222 }
223
GetFirstHandleOffset()224 virtual OffsetF GetFirstHandleOffset() const
225 {
226 return OffsetF();
227 }
228
GetSecondHandleOffset()229 virtual OffsetF GetSecondHandleOffset() const
230 {
231 return OffsetF();
232 }
233
GetSelectIndex(int32_t & start,int32_t & end)234 virtual void GetSelectIndex(int32_t& start, int32_t& end) const
235 {
236 start = textSelector_.GetTextStart();
237 end = textSelector_.GetTextEnd();
238 }
239
GetAvoidSoftKeyboardOffset()240 virtual const Dimension& GetAvoidSoftKeyboardOffset() const
241 {
242 return avoidKeyboardOffset_;
243 }
244
OnHandleAreaChanged()245 virtual void OnHandleAreaChanged() {}
246 virtual void SetIsTextDraggable(bool isTextDraggable = true) {}
247
IsStopBackPress()248 virtual bool IsStopBackPress() const
249 {
250 return true;
251 }
252
253 static void SetSelectionNode(const SelectedByMouseInfo& info);
254 static int32_t GetGraphemeClusterLength(const std::u16string& text, int32_t extend, bool checkPrev = false);
255 static void CalculateSelectedRect(
256 std::vector<RectF>& selectedRect, float longestLine, TextDirection direction = TextDirection::LTR);
257 static float GetSelectedBlankLineWidth();
258 static void CalculateSelectedRectEx(std::vector<RectF>& selectedRect, float lastLineBottom,
259 const std::optional<TextDirection>& direction = std::nullopt);
260 static bool UpdateSelectedBlankLineRect(RectF& rect, float blankWidth, TextAlign textAlign, float longestLine);
261 static void SelectedRectsToLineGroup(const std::vector<RectF>& selectedRect,
262 std::map<float, std::pair<RectF, std::vector<RectF>>>& lineGroup);
263 static TextAlign CheckTextAlignByDirection(TextAlign textAlign, TextDirection direction);
264
265 static void RevertLocalPointWithTransform(const RefPtr<FrameNode>& targetNode, OffsetF& point);
266 static bool HasRenderTransform(const RefPtr<FrameNode>& targetNode);
IsTextEditableForStylus()267 virtual bool IsTextEditableForStylus() const
268 {
269 return false;
270 }
271 static std::u16string ConvertStr8toStr16(const std::string& value);
isMouseOrTouchPad(SourceTool sourceTool)272 static bool isMouseOrTouchPad(SourceTool sourceTool)
273 {
274 return (sourceTool == SourceTool::MOUSE || sourceTool == SourceTool::TOUCHPAD);
275 }
276 std::u16string TruncateText(const std::u16string& text, const size_t& length) const;
277 size_t CountUtf16Chars(const std::u16string& s);
278 std::pair<std::string, std::string> DetectTextDiff(const std::string& latestContent);
279 static LayoutCalPolicy GetLayoutCalPolicy(LayoutWrapper* layoutWrapper, bool isHorizontal);
280 static float GetConstraintMaxLength(
281 LayoutWrapper* layoutWrapper, const LayoutConstraintF& constraint, bool isHorizontal);
282 static std::optional<float> GetCalcLayoutConstraintLength(LayoutWrapper* layoutWrapper, bool isMax, bool isWidth);
283 template <typename Callback>
ProcessAccessibilityTextChange(const std::string & currentContent,Callback && callback,const AceLogTag & logTag)284 void ProcessAccessibilityTextChange(const std::string& currentContent,
285 Callback&& callback, const AceLogTag& logTag)
286 {
287 if (suppressAccessibilityEvent_) {
288 auto [addedText, removedText] = DetectTextDiff(currentContent);
289 TAG_LOGI(logTag, "addedLen=%{public}d, removedLen=%{public}d",
290 static_cast<int>(addedText.length()), static_cast<int>(removedText.length()));
291 if (!removedText.empty()) {
292 callback(TextChangeType::REMOVE, removedText);
293 }
294 if (!addedText.empty()) {
295 callback(TextChangeType::ADD, addedText);
296 }
297 }
298 textCache_ = currentContent;
299 suppressAccessibilityEvent_ = true;
300 }
301
302 protected:
303 TextSelector textSelector_;
304 bool showSelect_ = true;
305 bool afterDragSelect_ = false;
306 bool releaseInDrop_ = false;
307 SourceTool sourceTool_ = SourceTool::UNKNOWN;
308 std::vector<std::u16string> dragContents_;
309 MouseStatus mouseStatus_ = MouseStatus::NONE;
310 RectF contentRect_;
311 Dimension avoidKeyboardOffset_ = 24.0_vp;
312 // for text change accessibility event
313 std::string textCache_;
314 bool suppressAccessibilityEvent_ = true;
315 ACE_DISALLOW_COPY_AND_MOVE(TextBase);
316 };
317 } // namespace OHOS::Ace::NG
318 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_TEXT_BASE_H
319