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 "core/common/container.h"
21 #include "core/components_ng/manager/select_overlay/select_overlay_client.h"
22 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
23 #include "core/components_ng/pattern/text_field/text_selector.h"
24 #include "core/components_ng/render/drawing.h"
25 #include "core/components_ng/render/paragraph.h"
26 #include "core/common/container.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28
29 namespace OHOS::Ace::NG {
30 using ParagraphT = std::variant<std::shared_ptr<RSParagraph>, RefPtr<Paragraph>>;
31
32 enum class MouseStatus { PRESSED, RELEASED, MOVE, NONE };
33
34 struct HandleMoveStatus {
35 bool isFirsthandle = false;
36 int32_t position = -1;
37 OffsetF handleOffset;
38
ResetHandleMoveStatus39 void Reset()
40 {
41 isFirsthandle = false;
42 position = -1;
43 }
44
IsValidHandleMoveStatus45 bool IsValid()
46 {
47 return position >= 0;
48 }
49 };
50
51 template<typename T>
GetTextCaretMetrics(RefPtr<FrameNode> & targetNode,CaretMetricsF & caretMetrics)52 void GetTextCaretMetrics(RefPtr<FrameNode>& targetNode, CaretMetricsF& caretMetrics)
53 {
54 CHECK_NULL_VOID(targetNode);
55 if (targetNode->GetTag() == V2::SEARCH_ETS_TAG) {
56 auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(targetNode->GetChildren().front());
57 CHECK_NULL_VOID(textFieldFrameNode);
58 auto textPattern = textFieldFrameNode->GetPattern<T>();
59 CHECK_NULL_VOID(textPattern);
60 textPattern->GetCaretMetrics(caretMetrics);
61 } else {
62 auto textPattern = targetNode->GetPattern<T>();
63 CHECK_NULL_VOID(textPattern);
64 textPattern->GetCaretMetrics(caretMetrics);
65 }
66 }
67 class TextBase : public SelectOverlayClient {
68 DECLARE_ACE_TYPE(TextBase, SelectOverlayClient);
69
70 public:
71 TextBase() = default;
72 ~TextBase() override = default;
73
GetContentOffset()74 virtual OffsetF GetContentOffset()
75 {
76 return OffsetF(0, 0);
77 }
78
OnBackPressed()79 virtual bool OnBackPressed()
80 {
81 return false;
82 }
83
IsSelected()84 virtual bool IsSelected() const
85 {
86 return textSelector_.IsValid() && !textSelector_.StartEqualToDest();
87 }
88
GetMouseStatus()89 MouseStatus GetMouseStatus() const
90 {
91 return mouseStatus_;
92 }
93
SetSelectionNode(const SelectedByMouseInfo & info)94 static void SetSelectionNode(const SelectedByMouseInfo& info)
95 {
96 auto pipeline = PipelineContext::GetCurrentContext();
97 CHECK_NULL_VOID(pipeline);
98 auto selectOverlayManager = pipeline->GetSelectOverlayManager();
99 selectOverlayManager->SetSelectedNodeByMouse(info);
100 }
101
102 static int32_t GetGraphemeClusterLength(const std::wstring& text, int32_t extend, bool checkPrev = false)
103 {
104 char16_t aroundChar = 0;
105 if (checkPrev) {
106 if (static_cast<size_t>(extend) <= text.length()) {
107 aroundChar = text[std::max(0, extend - 1)];
108 }
109 } else {
110 if (static_cast<size_t>(extend) <= (text.length())) {
111 aroundChar = text[std::min(static_cast<int32_t>(text.length() - 1), extend)];
112 }
113 }
114 return StringUtils::NotInUtf16Bmp(aroundChar) ? 2 : 1;
115 }
116
CalculateSelectedRect(std::vector<RectF> & selectedRect,float longestLine)117 static void CalculateSelectedRect(std::vector<RectF>& selectedRect, float longestLine)
118 {
119 if (selectedRect.size() <= 1) {
120 return;
121 }
122 std::map<float, RectF> lineGroup;
123 for (auto const& localRect : selectedRect) {
124 if (NearZero(localRect.Width()) && NearZero(localRect.Height())) {
125 continue;
126 }
127 auto it = lineGroup.find(localRect.GetY());
128 if (it == lineGroup.end()) {
129 lineGroup.emplace(localRect.GetY(), localRect);
130 } else {
131 auto lineRect = it->second;
132 it->second = lineRect.CombineRectT(localRect);
133 }
134 }
135 selectedRect.clear();
136 auto firstRect = lineGroup.begin()->second;
137 if (lineGroup.size() == 1) {
138 selectedRect.emplace_back(firstRect);
139 return;
140 }
141 firstRect.SetWidth(longestLine - firstRect.Left());
142 selectedRect.emplace_back(firstRect);
143 auto endRect = lineGroup.rbegin()->second;
144 endRect.SetWidth(endRect.Right());
145 endRect.SetLeft(0.0f);
146 selectedRect.emplace_back(endRect);
147 const int32_t drawMiddleLineNumberLimit = 2;
148 if (static_cast<int32_t>(lineGroup.size()) > drawMiddleLineNumberLimit || firstRect.Left() <= endRect.Right()) {
149 auto middleRect = RectF(0.0f, firstRect.Bottom(), longestLine, endRect.Top() - firstRect.Bottom());
150 selectedRect.emplace_back(middleRect);
151 }
152 }
153
154 // The methods that need to be implemented for input class components
GetCaretRect()155 virtual RectF GetCaretRect() const
156 {
157 return { 0, 0, 0, 0 };
158 }
159
ScrollToSafeArea()160 virtual void ScrollToSafeArea() const {}
161
UpdateKeyboardOffset(double positionY,double height)162 static void UpdateKeyboardOffset(double positionY, double height)
163 {
164 auto container = Container::Current();
165 CHECK_NULL_VOID(container);
166 auto context = PipelineContext::GetCurrentContext();
167 CHECK_NULL_VOID(context);
168 #ifdef WINDOW_SCENE_SUPPORTED
169 auto uiExtMgr = context->GetUIExtensionManager();
170 if (uiExtMgr && uiExtMgr->IsWindowTypeUIExtension(context)) {
171 return;
172 }
173 #endif
174 auto keyboardArea = container->GetKeyboardSafeArea();
175 auto keyboardLength = keyboardArea.bottom_.Length();
176 Rect keyboardRect;
177 keyboardRect.SetRect(0, keyboardArea.bottom_.start, 0, keyboardLength);
178 context->OnVirtualKeyboardAreaChange(keyboardRect, positionY, height);
179 }
180
GetCaretMetrics(CaretMetricsF & caretCaretMetric)181 virtual void GetCaretMetrics(CaretMetricsF& caretCaretMetric) {}
182
OnVirtualKeyboardAreaChanged()183 virtual void OnVirtualKeyboardAreaChanged() {}
184
185 protected:
186 TextSelector textSelector_;
187 bool showSelect_ = true;
188 std::vector<std::string> dragContents_;
189 MouseStatus mouseStatus_ = MouseStatus::NONE;
190 ACE_DISALLOW_COPY_AND_MOVE(TextBase);
191 };
192 } // namespace OHOS::Ace::NG
193 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_TEXT_BASE_H
194