• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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