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 #include "core/components_ng/pattern/text_field/text_input_response_area.h"
17
18 #include "base/geometry/dimension.h"
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/geometry/ng/size_t.h"
21 #include "base/memory/referenced.h"
22 #include "base/utils/utils.h"
23 #include "core/common/container.h"
24 #include "core/common/ime/text_input_type.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/theme/icon_theme.h"
27 #include "core/components_ng/pattern/stack/stack_pattern.h"
28 #include "core/components_ng/pattern/text/text_pattern.h"
29 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
30
31 namespace OHOS::Ace::NG {
32
33 namespace {
34 constexpr float MAX_FONT_SCALE = 2.0f;
35 constexpr Dimension ICON_MAX_SIZE = 40.0_vp;
36 constexpr Dimension DEFAULT_ICON_HOT_ZONE = 40.0_vp;
37 constexpr Dimension ICON_FOCUS_PADDING = 2.0_vp;
38 constexpr Dimension DEFAULT_HOVER_SIZE = 32.0_vp;
39 constexpr int HALF_SPACE = 2;
40 constexpr int DOUBLE_PADDING = 2;
41 } // namespace
42
43 // TextInputResponseArea begin
LayoutChild(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)44 void TextInputResponseArea::LayoutChild(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
45 {
46 auto frameNode = layoutWrapper->GetHostNode();
47 CHECK_NULL_VOID(frameNode);
48 auto children = frameNode->GetChildren();
49 CHECK_NULL_VOID(!children.empty());
50 auto pattern = frameNode->GetPattern<TextFieldPattern>();
51 CHECK_NULL_VOID(pattern);
52 auto textInputGeometryNode = layoutWrapper->GetGeometryNode();
53 CHECK_NULL_VOID(textInputGeometryNode);
54 auto contentRect = textInputGeometryNode->GetContentRect();
55 auto textInputFrameSize = textInputGeometryNode->GetFrameSize();
56 auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
57 CHECK_NULL_VOID(childWrapper);
58 auto childGeometryNode = childWrapper->GetGeometryNode();
59 CHECK_NULL_VOID(childGeometryNode);
60 auto childFrameSize = childGeometryNode->GetFrameSize();
61 auto childOffset = GetChildOffset(textInputFrameSize, contentRect, childFrameSize, nodeWidth);
62 childGeometryNode->SetFrameOffset(childOffset);
63 childWrapper->GetGeometryNode()->SetFrameSize(childFrameSize);
64 areaRect_.SetSize(childFrameSize);
65 areaRect_.SetOffset(childOffset);
66 childWrapper->Layout();
67 nodeWidth += childFrameSize.Width();
68 }
69
GetChildOffset(SizeF parentSize,RectF contentRect,SizeF childSize,float nodeWidth)70 OffsetF TextInputResponseArea::GetChildOffset(SizeF parentSize, RectF contentRect, SizeF childSize, float nodeWidth)
71 {
72 auto offset = Alignment::GetAlignPosition(parentSize, childSize, Alignment::CENTER);
73 auto textFieldPattern = hostPattern_.Upgrade();
74 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
75 auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
76 if (isRTL) {
77 return OffsetF(nodeWidth, offset.GetY());
78 } else {
79 return OffsetF(parentSize.Width() - childSize.Width() - nodeWidth, offset.GetY());
80 }
81 }
82
Measure(LayoutWrapper * layoutWrapper,int32_t index)83 SizeF TextInputResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
84 {
85 SizeF size(0, 0);
86 CHECK_NULL_RETURN(layoutWrapper, size);
87 auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
88 auto textfieldLayoutProperty = AceType::DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
89 CHECK_NULL_RETURN(textfieldLayoutProperty, size);
90 auto childLayoutConstraint = textfieldLayoutProperty->CreateChildConstraint();
91 CHECK_NULL_RETURN(childWrapper, size);
92 auto childLayoutProperty = childWrapper->GetLayoutProperty();
93 childWrapper->Measure(childLayoutConstraint);
94 auto geometryNode = childWrapper->GetGeometryNode();
95 CHECK_NULL_RETURN(geometryNode, size);
96 return geometryNode->GetFrameSize();
97 }
98
GetFrameSize(bool withSafeArea)99 SizeF TextInputResponseArea::GetFrameSize(bool withSafeArea)
100 {
101 auto frameNode = GetFrameNode();
102 CHECK_NULL_RETURN(frameNode, SizeF(0, 0));
103 auto geometryNode = frameNode->GetGeometryNode();
104 CHECK_NULL_RETURN(geometryNode, SizeF(0, 0));
105 return geometryNode->GetFrameSize(withSafeArea);
106 }
107
GetStackAlignment(const TextDirection & userDirection)108 Alignment TextInputResponseArea::GetStackAlignment(const TextDirection& userDirection)
109 {
110 bool isSysRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
111 if ((isSysRtl && userDirection == TextDirection::LTR) ||
112 (!isSysRtl && userDirection == TextDirection::RTL)) {
113 return Alignment::CENTER_RIGHT;
114 }
115 return Alignment::CENTER_LEFT;
116 }
117
CreateResponseAreaImageNode(const ImageSourceInfo & imageSourceInfo,ImageFit imageFit,const CalcSize & userDefinedIdealSize)118 RefPtr<FrameNode> TextInputResponseArea::CreateResponseAreaImageNode(const ImageSourceInfo& imageSourceInfo,
119 ImageFit imageFit, const CalcSize& userDefinedIdealSize)
120 {
121 auto imageNode = FrameNode::CreateFrameNode(
122 V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
123 CHECK_NULL_RETURN(imageNode, nullptr);
124 imageNode->SetDraggable(false);
125 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
126 CHECK_NULL_RETURN(imageLayoutProperty, nullptr); // return nullptr as this is severe situation
127 imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
128 imageLayoutProperty->UpdateImageFit(imageFit);
129 imageLayoutProperty->UpdateUserDefinedIdealSize(userDefinedIdealSize);
130 return imageNode;
131 }
132
SetHoverRect(RefPtr<FrameNode> & stackNode,RectF & rect,float iconSize,float hoverRectHeight,bool isFocus)133 void TextInputResponseArea::SetHoverRect(RefPtr<FrameNode>& stackNode, RectF& rect, float iconSize,
134 float hoverRectHeight, bool isFocus)
135 {
136 auto textFieldPattern = hostPattern_.Upgrade();
137 CHECK_NULL_VOID(textFieldPattern);
138 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
139 CHECK_NULL_VOID(layoutProperty);
140 CHECK_NULL_VOID(stackNode);
141 auto stackGeometryNode = stackNode->GetGeometryNode();
142 CHECK_NULL_VOID(stackGeometryNode);
143 auto stackRect = stackGeometryNode->GetFrameRect();
144 auto imageFrameNode = AceType::DynamicCast<FrameNode>(stackNode->GetFirstChild());
145 CHECK_NULL_VOID(imageFrameNode);
146 auto imageGeometryNode = imageFrameNode->GetGeometryNode();
147 CHECK_NULL_VOID(imageGeometryNode);
148 auto imageRect = imageGeometryNode->GetFrameRect();
149 if (isFocus) {
150 hoverRectHeight = hoverRectHeight - ICON_FOCUS_PADDING.ConvertToPx();
151 }
152
153 auto iconHoverPadding = (hoverRectHeight - iconSize) / HALF_SPACE;
154 auto stackHoverPadding = (hoverRectHeight - stackRect.Height()) / HALF_SPACE;
155 auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
156 if (isRTL) {
157 rect = RectF(stackRect.GetX() + stackRect.Width() - imageRect.Width() - iconHoverPadding,
158 stackRect.GetY() - stackHoverPadding, hoverRectHeight, hoverRectHeight);
159 } else {
160 rect = RectF(stackRect.GetX() - iconHoverPadding, stackRect.GetY() - stackHoverPadding,
161 hoverRectHeight, hoverRectHeight);
162 }
163 }
164 // TextInputResponseArea end
165
166 // PasswordResponseArea begin
InitResponseArea()167 void PasswordResponseArea::InitResponseArea()
168 {
169 ClearArea();
170 auto pattern = hostPattern_.Upgrade();
171 CHECK_NULL_VOID(pattern);
172 auto host = pattern->GetHost();
173 CHECK_NULL_VOID(host);
174 if (!IsShowPasswordIcon()) {
175 return;
176 }
177 auto passwordNode = CreateNode();
178 CHECK_NULL_VOID(passwordNode);
179 passwordNode->MountToParent(host);
180 }
181
GetFrameNode()182 const RefPtr<FrameNode> PasswordResponseArea::GetFrameNode()
183 {
184 auto frameNode = passwordNode_.Upgrade();
185 CHECK_NULL_RETURN(frameNode, nullptr);
186 auto stackNode = frameNode->GetParent();
187 CHECK_NULL_RETURN(stackNode, nullptr);
188 auto ret = AceType::DynamicCast<FrameNode>(stackNode);
189 CHECK_NULL_RETURN(ret, nullptr);
190 return ret;
191 }
192
CreateNode()193 RefPtr<FrameNode> PasswordResponseArea::CreateNode()
194 {
195 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
196 CHECK_NULL_RETURN(textFieldPattern, nullptr);
197 auto iconSize = GetIconSize();
198 auto rightOffset = GetIconRightOffset();
199 auto hotZoneSize = iconSize + rightOffset;
200
201 auto stackNode = FrameNode::CreateFrameNode(
202 V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
203 auto stackLayoutProperty = stackNode->GetLayoutProperty<LayoutProperty>();
204 CHECK_NULL_RETURN(stackLayoutProperty, nullptr);
205 stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(hotZoneSize), std::nullopt));
206 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
207 CHECK_NULL_RETURN(layoutProperty, nullptr);
208 stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
209 AddEvent(stackNode);
210 stackNode->MarkModifyDone();
211
212 if (IsShowSymbol() && SystemProperties::IsNeedSymbol()) {
213 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
214 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
215 CHECK_NULL_RETURN(symbolNode, nullptr);
216 passwordNode_ = symbolNode;
217 InitSymbolEffectOptions();
218 UpdateSymbolSource();
219
220 symbolNode->MountToParent(stackNode);
221 stackNode_ = stackNode;
222 return stackNode;
223 }
224
225 LoadImageSourceInfo();
226 auto currentImageSourceInfo = GetCurrentSourceInfo();
227 CHECK_NULL_RETURN(currentImageSourceInfo, nullptr);
228 auto imageNode = CreateResponseAreaImageNode(currentImageSourceInfo.value(), ImageFit::FILL,
229 CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
230 CHECK_NULL_RETURN(imageNode, nullptr);
231
232 passwordNode_ = imageNode;
233 AddImageEventOnError();
234 imageNode->MarkModifyDone();
235 imageNode->MountToParent(stackNode);
236 stackNode_ = stackNode;
237 return stackNode;
238 }
239
AddIconHotZoneRect()240 void PasswordResponseArea::AddIconHotZoneRect()
241 {
242 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
243 return;
244 }
245 CHECK_NULL_VOID(stackNode_);
246 auto stackGeometryNode = stackNode_->GetGeometryNode();
247 CHECK_NULL_VOID(stackGeometryNode);
248 auto stackRect = stackGeometryNode->GetFrameRect();
249
250 auto iconSize = stackRect.Width() - GetIconRightOffset();
251 auto hotZoneHeight = DEFAULT_ICON_HOT_ZONE.ConvertToPx();
252 hotZoneHeight = passwordHoverSize_ > hotZoneHeight ? passwordHoverSize_ : hotZoneHeight;
253 auto hotZoneX = - (hotZoneHeight - iconSize) / HALF_SPACE;
254 auto hotZoneY = - (hotZoneHeight - iconSize) / HALF_SPACE;
255
256 OffsetF hotZoneOffset;
257 hotZoneOffset.SetX(hotZoneX);
258 hotZoneOffset.SetY(hotZoneY);
259 SizeF hotZoneSize;
260 hotZoneSize.SetWidth(hotZoneHeight);
261 hotZoneSize.SetHeight(hotZoneHeight);
262 DimensionRect hotZoneRegion;
263 hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize.Width()), Dimension(hotZoneSize.Height())));
264 hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
265
266 std::vector<DimensionRect> mouseRegion;
267 mouseRegion.emplace_back(hotZoneRegion);
268
269 auto stackGestureHub = stackNode_->GetOrCreateGestureEventHub();
270 CHECK_NULL_VOID(stackGestureHub);
271 stackGestureHub->SetMouseResponseRegion(mouseRegion);
272
273 std::vector<DimensionRect> responseRegion;
274 responseRegion.emplace_back(hotZoneRegion);
275 stackGestureHub->SetResponseRegion(responseRegion);
276 }
277
CreateIconRect(RoundRect & paintRect,bool isFocus)278 void PasswordResponseArea::CreateIconRect(RoundRect& paintRect, bool isFocus)
279 {
280 CHECK_NULL_VOID(stackNode_);
281 auto imageFrameNode = AceType::DynamicCast<FrameNode>(stackNode_->GetFirstChild());
282 CHECK_NULL_VOID(imageFrameNode);
283 auto imageGeometryNode = imageFrameNode->GetGeometryNode();
284 CHECK_NULL_VOID(imageGeometryNode);
285 auto imageRect = imageGeometryNode->GetFrameRect();
286 auto textInputNode = stackNode_->GetParentFrameNode();
287 CHECK_NULL_VOID(textInputNode);
288 auto textInputRect = textInputNode->GetGeometryNode()->GetFrameRect();
289 auto iconSize = imageRect.Height();
290 auto defaultRectHeight = DEFAULT_HOVER_SIZE.ConvertToPx();
291 auto rectHeight = iconSize > defaultRectHeight ? iconSize : defaultRectHeight;
292 auto hoverRectHeight = rectHeight > textInputRect.Height() ? textInputRect.Height() : rectHeight;
293 auto maxHoverRectHeight = iconSize + DOUBLE_PADDING * GetIconRightOffset();
294 hoverRectHeight = hoverRectHeight > maxHoverRectHeight ? maxHoverRectHeight : hoverRectHeight;
295 passwordHoverSize_ = hoverRectHeight;
296 RectF rect;
297 SetHoverRect(stackNode_, rect, iconSize, hoverRectHeight, isFocus);
298 paintRect.SetRect(rect);
299 }
300
AddEvent(const RefPtr<FrameNode> & node)301 void PasswordResponseArea::AddEvent(const RefPtr<FrameNode>& node)
302 {
303 CHECK_NULL_VOID(node);
304 auto focusHub = node->GetOrCreateFocusHub();
305 CHECK_NULL_VOID(focusHub);
306 auto gesture = node->GetOrCreateGestureEventHub();
307 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
308 auto button = weak.Upgrade();
309 CHECK_NULL_VOID(button);
310 button->OnPasswordIconClicked();
311 auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
312 CHECK_NULL_VOID(context);
313 auto theme = context->GetTheme<TextFieldTheme>();
314 CHECK_NULL_VOID(theme);
315 auto node = button->GetFrameNode();
316 CHECK_NULL_VOID(node);
317 auto message = !button->IsObscured() ? theme->GetHasShowedPassword() : theme->GetHasHiddenPassword();
318 node->OnAccessibilityEvent(AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY, message);
319 };
320 auto mouseTask = [id = Container::CurrentId(), weak = hostPattern_](MouseInfo& info) {
321 info.SetStopPropagation(true);
322 auto pattern = weak.Upgrade();
323 CHECK_NULL_VOID(pattern);
324 auto textfield = DynamicCast<TextFieldPattern>(pattern);
325 CHECK_NULL_VOID(textfield);
326 textfield->RestoreDefaultMouseState();
327 };
328 auto touchTask = [weak = WeakClaim(this)](TouchEventInfo& info) {
329 info.SetStopPropagation(true);
330 };
331
332 auto inputHub = node->GetOrCreateInputEventHub();
333 auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseTask));
334 inputHub->AddOnMouseEvent(mouseEvent);
335 gesture->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(clickCallback)));
336 gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
337 }
338
Refresh()339 void PasswordResponseArea::Refresh()
340 {
341 auto iconNode = passwordNode_.Upgrade();
342 if (!iconNode) {
343 InitResponseArea();
344 return;
345 }
346
347 auto textFieldPattern = hostPattern_.Upgrade();
348 if (textFieldPattern && stackNode_) {
349 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
350 auto stackLayoutProperty = stackNode_->GetLayoutProperty<LayoutProperty>();
351 if (stackLayoutProperty && layoutProperty) {
352 stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
353 }
354 }
355
356 // update node symbol
357 if (IsShowSymbol() && IsSymbolIcon() && SystemProperties::IsNeedSymbol()) {
358 UpdateSymbolColor();
359 return;
360 }
361
362 // update node image
363 if (!IsShowSymbol() && !IsSymbolIcon()) {
364 auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
365 CHECK_NULL_VOID(imageLayoutProperty);
366 auto currentSrc = imageLayoutProperty->GetImageSourceInfoValue().GetSrc();
367 LoadImageSourceInfo();
368 auto src = isObscured_ ? hideIcon_->GetSrc() : showIcon_->GetSrc();
369 if (currentSrc != src) {
370 UpdateImageSource();
371 }
372 return;
373 }
374
375 ReplaceNode();
376 }
377
ClearArea()378 void PasswordResponseArea::ClearArea()
379 {
380 auto hostPattern = hostPattern_.Upgrade();
381 CHECK_NULL_VOID(hostPattern);
382 auto host = hostPattern->GetHost();
383 CHECK_NULL_VOID(host);
384 CHECK_NULL_VOID(stackNode_);
385 host->RemoveChildAndReturnIndex(stackNode_);
386 passwordNode_.Reset();
387 areaRect_.Reset();
388 }
389
ReplaceNode()390 void PasswordResponseArea::ReplaceNode()
391 {
392 auto oldFrameNode = passwordNode_.Upgrade();
393 CHECK_NULL_VOID(oldFrameNode);
394
395 if (IsShowSymbol() && SystemProperties::IsNeedSymbol()) {
396 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
397 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
398 CHECK_NULL_VOID(symbolNode);
399 stackNode_->ReplaceChild(oldFrameNode, symbolNode);
400 passwordNode_ = symbolNode;
401 InitSymbolEffectOptions();
402 UpdateSymbolSource();
403 return;
404 }
405
406 auto iconSize = GetIconSize();
407 LoadImageSourceInfo();
408 auto currentImageSourceInfo = GetCurrentSourceInfo();
409 CHECK_NULL_VOID(currentImageSourceInfo);
410 auto imageNode = CreateResponseAreaImageNode(currentImageSourceInfo.value(), ImageFit::FILL,
411 CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
412 CHECK_NULL_VOID(imageNode);
413
414 stackNode_->ReplaceChild(oldFrameNode, imageNode);
415 passwordNode_ = imageNode;
416 AddImageEventOnError();
417 imageNode->MarkModifyDone();
418 imageNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
419 }
420
OnPasswordIconClicked()421 void PasswordResponseArea::OnPasswordIconClicked()
422 {
423 isObscured_ = !isObscured_;
424 ChangeObscuredState();
425 }
426
UpdatePasswordIconColor(const Color & color)427 void PasswordResponseArea::UpdatePasswordIconColor(const Color& color)
428 {
429 showIcon_->SetFillColor(color);
430 hideIcon_->SetFillColor(color);
431
432 if (IsSymbolIcon()) {
433 UpdateSymbolColor();
434 } else {
435 UpdateImageSource();
436 }
437 }
438
ChangeObscuredState()439 void PasswordResponseArea::ChangeObscuredState()
440 {
441 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
442 CHECK_NULL_VOID(textFieldPattern);
443 if (IsSymbolIcon() && SystemProperties::IsNeedSymbol()) {
444 UpdateSymbolSource();
445 } else {
446 UpdateImageSource();
447 }
448 textFieldPattern->OnObscuredChanged(isObscured_);
449 }
450
Measure(LayoutWrapper * layoutWrapper,int32_t index)451 SizeF PasswordResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
452 {
453 if (!IsShowPasswordIcon()) {
454 return SizeF(0, 0);
455 }
456 auto textInputMeasure = TextInputResponseArea::Measure(layoutWrapper, index);
457 AddIconHotZoneRect();
458 return textInputMeasure;
459 }
460
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)461 void PasswordResponseArea::Layout(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
462 {
463 if (!IsShowPasswordIcon()) {
464 return;
465 }
466 LayoutChild(layoutWrapper, index, nodeWidth);
467 }
468
GetIconSize()469 float PasswordResponseArea::GetIconSize()
470 {
471 auto textFieldPattern = hostPattern_.Upgrade();
472 CHECK_NULL_RETURN(textFieldPattern, 0.0f);
473 auto tmpHost = textFieldPattern->GetHost();
474 CHECK_NULL_RETURN(tmpHost, 0.0f);
475 auto pipeline = tmpHost->GetContextRefPtr();
476 CHECK_NULL_RETURN(pipeline, 0.0f);
477 auto themeManager = pipeline->GetThemeManager();
478 CHECK_NULL_RETURN(themeManager, 0.0f);
479 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
480 CHECK_NULL_RETURN(textFieldTheme, 0.0f);
481 auto iconSize = textFieldTheme->GetIconSize().ConvertToPx();
482 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
483 iconSize = textFieldTheme->GetPasswordIconSize().ConvertToPx();
484 }
485 return static_cast<float>(iconSize);
486 }
487
GetIconRightOffset()488 float PasswordResponseArea::GetIconRightOffset()
489 {
490 auto textFieldPattern = hostPattern_.Upgrade();
491 CHECK_NULL_RETURN(textFieldPattern, 0.0f);
492 auto tmpHost = textFieldPattern->GetHost();
493 auto pipeline = tmpHost->GetContextRefPtr();
494 CHECK_NULL_RETURN(pipeline, 0.0f);
495 auto themeManager = pipeline->GetThemeManager();
496 CHECK_NULL_RETURN(themeManager, 0.0f);
497 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
498 CHECK_NULL_RETURN(textFieldTheme, 0.0f);
499 auto themePadding = textFieldTheme->GetPadding();
500 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
501 auto passwordIconPadding = textFieldTheme->GetPasswordIconPadding();
502 return static_cast<float>(passwordIconPadding.ConvertToPx());
503 }
504 return static_cast<float>(themePadding.Left().ConvertToPx());
505 }
506
LoadImageSourceInfo()507 void PasswordResponseArea::LoadImageSourceInfo()
508 {
509 auto textFieldPattern = hostPattern_.Upgrade();
510 CHECK_NULL_VOID(textFieldPattern);
511 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
512 CHECK_NULL_VOID(layoutProperty);
513 showIcon_ = layoutProperty->GetShowPasswordSourceInfoValue(GetDefaultSourceInfo(false));
514 hideIcon_ = layoutProperty->GetHidePasswordSourceInfoValue(GetDefaultSourceInfo(true));
515 auto tmpHost = textFieldPattern->GetHost();
516 CHECK_NULL_VOID(tmpHost);
517 auto pipeline = tmpHost->GetContextRefPtr();
518 CHECK_NULL_VOID(pipeline);
519 auto themeManager = pipeline->GetThemeManager();
520 CHECK_NULL_VOID(themeManager);
521 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>(tmpHost->GetThemeScopeId());
522 CHECK_NULL_VOID(textFieldTheme);
523 if (showIcon_->GetResourceId() == InternalResource::ResourceId::SHOW_PASSWORD_SVG) {
524 showIcon_->SetFillColor(textFieldTheme->GetTextColor());
525 }
526 if (hideIcon_->GetResourceId() == InternalResource::ResourceId::HIDE_PASSWORD_SVG) {
527 hideIcon_->SetFillColor(textFieldTheme->GetTextColor());
528 }
529 if (layoutProperty->GetIsDisabledValue(false)) {
530 auto iconTheme = pipeline->GetTheme<IconTheme>();
531 CHECK_NULL_VOID(iconTheme);
532 auto textDisableColor = textFieldTheme->GetTextColorDisable();
533 auto hideIconPath = iconTheme->GetIconPath(hideIcon_->GetResourceId());
534 hideIcon_->SetSrc(hideIconPath, textDisableColor);
535 auto showIconPath = iconTheme->GetIconPath(showIcon_->GetResourceId());
536 showIcon_->SetSrc(showIconPath, textDisableColor);
537 UpdateImageSource();
538 }
539 }
540
AddImageEventOnError()541 void PasswordResponseArea::AddImageEventOnError()
542 {
543 auto imageNode = passwordNode_.Upgrade();
544 auto eventHub = imageNode->GetEventHub<ImageEventHub>();
545 CHECK_NULL_VOID(eventHub);
546 eventHub->SetOnError([ weakNode = WeakClaim(AceType::RawPtr(imageNode)), weakArea = WeakClaim(this) ]
547 (const LoadImageFailEvent& info) {
548 auto host = weakNode.Upgrade();
549 CHECK_NULL_VOID(host);
550 auto area = weakArea.Upgrade();
551 CHECK_NULL_VOID(area);
552 auto imagePattern = host->GetPattern<ImagePattern>();
553 CHECK_NULL_VOID(imagePattern);
554 auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
555 CHECK_NULL_VOID(layoutProperty);
556 layoutProperty->UpdateImageSourceInfo(area->GetDefaultSourceInfo(area->isObscured_));
557 imagePattern->LoadImageDataIfNeed();
558 });
559 }
560
GetDefaultSourceInfo(bool isObscured)561 ImageSourceInfo PasswordResponseArea::GetDefaultSourceInfo(bool isObscured)
562 {
563 if (isObscured) {
564 ImageSourceInfo hideSystemSourceInfo;
565 hideSystemSourceInfo.SetResourceId(InternalResource::ResourceId::HIDE_PASSWORD_SVG);
566 return hideSystemSourceInfo;
567 }
568 ImageSourceInfo showSystemSourceInfo;
569 showSystemSourceInfo.SetResourceId(InternalResource::ResourceId::SHOW_PASSWORD_SVG);
570 return showSystemSourceInfo;
571 }
572
UpdateImageSource()573 void PasswordResponseArea::UpdateImageSource()
574 {
575 auto frameNode = passwordNode_.Upgrade();
576 CHECK_NULL_VOID(frameNode);
577 auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
578 CHECK_NULL_VOID(layoutProperty);
579 auto currentImageSourceInfo = GetCurrentSourceInfo();
580 CHECK_NULL_VOID(currentImageSourceInfo);
581 layoutProperty->UpdateImageSourceInfo(currentImageSourceInfo.value());
582 auto imagePattern = frameNode->GetPattern<ImagePattern>();
583 CHECK_NULL_VOID(imagePattern);
584 imagePattern->LoadImageDataIfNeed();
585 }
586
UpdateSymbolSource()587 void PasswordResponseArea::UpdateSymbolSource()
588 {
589 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
590 CHECK_NULL_VOID(textFieldPattern);
591 auto host = textFieldPattern->GetHost();
592 CHECK_NULL_VOID(host);
593 auto pipeline = host->GetContextRefPtr();
594 CHECK_NULL_VOID(pipeline);
595 auto themeManager = pipeline->GetThemeManager();
596 CHECK_NULL_VOID(themeManager);
597 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>(host->GetThemeScopeId());
598 CHECK_NULL_VOID(textFieldTheme);
599 auto symbolNode = passwordNode_.Upgrade();
600 CHECK_NULL_VOID(symbolNode);
601 auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
602 CHECK_NULL_VOID(symbolProperty);
603 auto currentSymbolId = isObscured_ ? textFieldTheme->GetHideSymbolId() : textFieldTheme->GetShowSymbolId();
604 symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(currentSymbolId));
605 symbolProperty->UpdateFontSize(textFieldTheme->GetSymbolSize());
606 symbolColor_ = textFieldTheme->GetSymbolColor();
607 symbolProperty->UpdateSymbolColorList({ symbolColor_ });
608 symbolProperty->UpdateMaxFontScale(MAX_FONT_SCALE);
609 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
610 symbolProperty->UpdateFontSize(textFieldTheme->GetPasswordIconSize());
611 }
612
613 symbolNode->MarkModifyDone();
614 symbolNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
615 }
616
UpdateSymbolColor()617 void PasswordResponseArea::UpdateSymbolColor()
618 {
619 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
620 CHECK_NULL_VOID(textFieldPattern);
621 auto host = textFieldPattern->GetHost();
622 CHECK_NULL_VOID(host);
623 auto pipeline = host->GetContextRefPtr();
624 CHECK_NULL_VOID(pipeline);
625 auto themeManager = pipeline->GetThemeManager();
626 CHECK_NULL_VOID(themeManager);
627 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>(host->GetThemeScopeId());
628 CHECK_NULL_VOID(textFieldTheme);
629 auto symbolNode = passwordNode_.Upgrade();
630 CHECK_NULL_VOID(symbolNode);
631 auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
632 CHECK_NULL_VOID(symbolProperty);
633 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
634 CHECK_NULL_VOID(layoutProperty);
635
636 Color color = textFieldTheme->GetSymbolColor();
637 if (layoutProperty->GetIsDisabledValue(false)) {
638 color = textFieldTheme->GetTextColorDisable();
639 }
640
641 // frame bug, MarkDirtyNode will trigger symbol effect
642 // add a temp variable for record color, prevent frequent MarkDirtyNode triggering
643 if (symbolColor_ != color) {
644 symbolColor_ = color;
645 symbolProperty->UpdateSymbolColorList({ symbolColor_ });
646 symbolNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
647 }
648 }
649
InitSymbolEffectOptions()650 void PasswordResponseArea::InitSymbolEffectOptions()
651 {
652 auto symbolNode = passwordNode_.Upgrade();
653 CHECK_NULL_VOID(symbolNode);
654 auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
655 CHECK_NULL_VOID(symbolProperty);
656 auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
657 symbolEffectOptions.SetEffectType(SymbolEffectType::REPLACE);
658 symbolEffectOptions.SetScopeType(Ace::ScopeType::WHOLE);
659 symbolEffectOptions.SetIsTxtActive(true);
660 symbolEffectOptions.SetIsTxtActiveSource(0);
661 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
662 }
663
IsShowSymbol()664 bool PasswordResponseArea::IsShowSymbol()
665 {
666 auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
667 CHECK_NULL_RETURN(textFieldPattern, false);
668 return textFieldPattern->IsShowPasswordSymbol();
669 }
670
IsSymbolIcon()671 bool PasswordResponseArea::IsSymbolIcon()
672 {
673 auto iconFrameNode = passwordNode_.Upgrade();
674 CHECK_NULL_RETURN(iconFrameNode, false);
675 return iconFrameNode->GetTag() == V2::SYMBOL_ETS_TAG;
676 }
677
IsShowPasswordIcon()678 bool PasswordResponseArea::IsShowPasswordIcon()
679 {
680 auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
681 CHECK_NULL_RETURN(textFieldPattern, false);
682 return textFieldPattern->IsShowPasswordIcon();
683 } // PasswordResponseArea end
684
685 // UnitResponseArea begin
InitResponseArea()686 void UnitResponseArea::InitResponseArea()
687 {
688 auto pattern = hostPattern_.Upgrade();
689 CHECK_NULL_VOID(pattern);
690 auto host = pattern->GetHost();
691 CHECK_NULL_VOID(host);
692 if (!IsShowUnit()) {
693 return;
694 }
695 CHECK_NULL_VOID(unitNode_);
696 unitNode_->MountToParent(host);
697 }
698
GetFrameNode()699 const RefPtr<FrameNode> UnitResponseArea::GetFrameNode()
700 {
701 auto frameNode = AceType::DynamicCast<FrameNode>(unitNode_);
702 CHECK_NULL_RETURN(frameNode, nullptr);
703 return frameNode;
704 }
705
ClearArea()706 void UnitResponseArea::ClearArea()
707 {
708 auto hostPattern = hostPattern_.Upgrade();
709 CHECK_NULL_VOID(hostPattern);
710 auto host = hostPattern->GetHost();
711 CHECK_NULL_VOID(host);
712 CHECK_NULL_VOID(unitNode_);
713 host->RemoveChildAndReturnIndex(unitNode_);
714 areaRect_.Reset();
715 }
716
Measure(LayoutWrapper * layoutWrapper,int32_t index)717 SizeF UnitResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
718 {
719 if (!IsShowUnit()) {
720 return SizeF(0, 0);
721 }
722 return TextInputResponseArea::Measure(layoutWrapper, index);
723 }
724
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)725 void UnitResponseArea::Layout(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
726 {
727 if (!IsShowUnit()) {
728 return;
729 }
730 LayoutChild(layoutWrapper, index, nodeWidth);
731 }
732
IsShowUnit()733 bool UnitResponseArea::IsShowUnit()
734 {
735 auto pattern = hostPattern_.Upgrade();
736 CHECK_NULL_RETURN(pattern, false);
737 auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern);
738 CHECK_NULL_RETURN(textFieldPattern, false);
739 return textFieldPattern->IsUnderlineMode();
740 } // UnitResponseArea end
741
InitResponseArea()742 void CleanNodeResponseArea::InitResponseArea()
743 {
744 auto pattern = hostPattern_.Upgrade();
745 CHECK_NULL_VOID(pattern);
746 auto host = pattern->GetHost();
747 CHECK_NULL_VOID(host);
748 LoadingImageProperty();
749 auto cleanNode = CreateNode();
750 CHECK_NULL_VOID(cleanNode);
751 cleanNode->MountToParent(host);
752 }
753
Measure(LayoutWrapper * layoutWrapper,int32_t index)754 SizeF CleanNodeResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
755 {
756 auto textInputMeasure = TextInputResponseArea::Measure(layoutWrapper, index);
757 AddIconHotZoneRect();
758 return textInputMeasure;
759 }
760
AddIconHotZoneRect()761 void CleanNodeResponseArea::AddIconHotZoneRect()
762 {
763 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
764 return;
765 }
766 CHECK_NULL_VOID(cleanNode_);
767 auto iconSize = GetIconSize();
768 auto hotZoneHeight = DEFAULT_ICON_HOT_ZONE.ConvertToPx();
769 hotZoneHeight = cancelHoverSize_ > hotZoneHeight ? cancelHoverSize_ : hotZoneHeight;
770 auto hotZoneX = - (hotZoneHeight - iconSize) / HALF_SPACE;
771 auto hotZoneY = - (hotZoneHeight - iconSize) / HALF_SPACE;
772
773 OffsetF hotZoneOffset;
774 hotZoneOffset.SetX(hotZoneX);
775 hotZoneOffset.SetY(hotZoneY);
776 SizeF hotZoneSize;
777 hotZoneSize.SetWidth(hotZoneHeight);
778 hotZoneSize.SetHeight(hotZoneHeight);
779 DimensionRect hotZoneRegion;
780 hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize.Width()), Dimension(hotZoneSize.Height())));
781 hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
782
783 std::vector<DimensionRect> mouseRegion;
784 mouseRegion.emplace_back(hotZoneRegion);
785
786 auto stackGestureHub = cleanNode_->GetOrCreateGestureEventHub();
787 CHECK_NULL_VOID(stackGestureHub);
788 stackGestureHub->SetMouseResponseRegion(mouseRegion);
789
790 std::vector<DimensionRect> responseRegion;
791 responseRegion.emplace_back(hotZoneRegion);
792 stackGestureHub->SetResponseRegion(responseRegion);
793 }
794
GetCancelButtonPadding(const RefPtr<TextFieldTheme> & textFieldTheme)795 float GetCancelButtonPadding(const RefPtr<TextFieldTheme>& textFieldTheme)
796 {
797 CHECK_NULL_RETURN(textFieldTheme, 0.0f);
798 auto themePadding = textFieldTheme->GetPadding();
799 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
800 auto cancelButtonPadding = textFieldTheme->GetCancelIconPadding();
801 return static_cast<float>(cancelButtonPadding.ConvertToPx());
802 }
803 return static_cast<float>(themePadding.Left().ConvertToPx());
804 }
805
CreateIconRect(RoundRect & paintRect,bool isFocus)806 void CleanNodeResponseArea::CreateIconRect(RoundRect& paintRect, bool isFocus)
807 {
808 CHECK_NULL_VOID(cleanNode_);
809 auto pattern = hostPattern_.Upgrade();
810 CHECK_NULL_VOID(pattern);
811 auto imageFrameNode = AceType::DynamicCast<FrameNode>(cleanNode_->GetFirstChild());
812 CHECK_NULL_VOID(imageFrameNode);
813 auto imageGeometryNode = imageFrameNode->GetGeometryNode();
814 CHECK_NULL_VOID(imageGeometryNode);
815 auto imageRect = imageGeometryNode->GetFrameRect();
816 auto textInputNode = cleanNode_->GetParentFrameNode();
817 CHECK_NULL_VOID(textInputNode);
818 auto textInputRect = textInputNode->GetGeometryNode()->GetFrameRect();
819 auto iconSize = imageRect.Height();
820 auto defaultRectHeight = DEFAULT_HOVER_SIZE.ConvertToPx();
821 auto host = pattern->GetHost();
822 CHECK_NULL_VOID(host);
823 auto pipeline = host->GetContext();
824 CHECK_NULL_VOID(pipeline);
825 auto theme = pipeline->GetTheme<TextFieldTheme>(host->GetThemeScopeId());
826 CHECK_NULL_VOID(theme);
827 auto rectHeight = iconSize > defaultRectHeight ? iconSize : defaultRectHeight;
828 auto hoverRectHeight = rectHeight > textInputRect.Height() ? textInputRect.Height() : rectHeight;
829 auto maxHoverRectHeight = iconSize + DOUBLE_PADDING * GetCancelButtonPadding(theme);
830 hoverRectHeight = hoverRectHeight > maxHoverRectHeight ? maxHoverRectHeight : hoverRectHeight;
831 cancelHoverSize_ = hoverRectHeight;
832 RectF rect;
833 SetHoverRect(cleanNode_, rect, iconSize, hoverRectHeight, isFocus);
834 paintRect.SetRect(rect);
835 }
836
IsShowClean() const837 bool CleanNodeResponseArea::IsShowClean() const
838 {
839 auto pattern = hostPattern_.Upgrade();
840 CHECK_NULL_RETURN(pattern, false);
841 auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern);
842 CHECK_NULL_RETURN(textFieldPattern, false);
843 return textFieldPattern->IsShowCancelButtonMode();
844 }
845
IsShowSymbol() const846 bool CleanNodeResponseArea::IsShowSymbol() const
847 {
848 auto pattern = hostPattern_.Upgrade();
849 CHECK_NULL_RETURN(pattern, false);
850 auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
851 CHECK_NULL_RETURN(textFieldLayoutProperty, false);
852 return textFieldLayoutProperty->GetIsShowSymbolValue(true);
853 }
854
IsSymbolIcon() const855 bool CleanNodeResponseArea::IsSymbolIcon() const
856 {
857 CHECK_NULL_RETURN(cleanNode_, false);
858 CHECK_NULL_RETURN(cleanNode_->GetFirstChild(), false);
859 auto iconFrameNode = AceType::DynamicCast<FrameNode>(cleanNode_->GetFirstChild());
860 CHECK_NULL_RETURN(iconFrameNode, false);
861 return iconFrameNode->GetTag() == V2::SYMBOL_ETS_TAG;
862 }
863
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)864 void CleanNodeResponseArea::Layout(LayoutWrapper *layoutWrapper, int32_t index, float &nodeWidth)
865 {
866 if (!IsShowClean()) {
867 return;
868 }
869 LayoutChild(layoutWrapper, index, nodeWidth);
870 }
871
GetFrameNode()872 const RefPtr<FrameNode> CleanNodeResponseArea::GetFrameNode()
873 {
874 return cleanNode_;
875 }
876
CreateNode()877 RefPtr<FrameNode> CleanNodeResponseArea::CreateNode()
878 {
879 auto stackNode = FrameNode::CreateFrameNode(
880 V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
881 auto stackLayoutProperty = stackNode->GetLayoutProperty<LayoutProperty>();
882 CHECK_NULL_RETURN(stackLayoutProperty, nullptr);
883 stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), std::nullopt));
884 stackLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
885 auto textFieldPattern = hostPattern_.Upgrade();
886 CHECK_NULL_RETURN(textFieldPattern, nullptr);
887 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
888 CHECK_NULL_RETURN(layoutProperty, nullptr);
889 stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
890 stackNode->MarkModifyDone();
891
892 if (IsShowSymbol() && SystemProperties::IsNeedSymbol()) {
893 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
894 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
895 CHECK_NULL_RETURN(symbolNode, nullptr);
896 cleanNode_ = stackNode;
897 symbolNode->MountToParent(stackNode);
898 InitClickEvent(stackNode);
899 SetCancelSymbolIconSize();
900 UpdateSymbolSource();
901 return stackNode;
902 }
903
904 auto info = CreateImageSourceInfo();
905 auto imageNode = CreateResponseAreaImageNode(info, ImageFit::COVER, CalcSize(CalcLength(0.0f), CalcLength(0.0f)));
906 CHECK_NULL_RETURN(imageNode, nullptr);
907 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
908 CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
909 imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
910
911 cleanNode_ = stackNode;
912 imageNode->MarkModifyDone();
913 imageNode->MountToParent(stackNode);
914 InitClickEvent(stackNode);
915 return stackNode;
916 }
917
SetCancelSymbolIconSize()918 void CleanNodeResponseArea::SetCancelSymbolIconSize()
919 {
920 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
921 CHECK_NULL_VOID(textFieldPattern);
922 auto host = textFieldPattern->GetHost();
923 CHECK_NULL_VOID(host);
924 auto pipeline = host->GetContextRefPtr();
925 CHECK_NULL_VOID(pipeline);
926 auto themeManager = pipeline->GetThemeManager();
927 CHECK_NULL_VOID(themeManager);
928 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
929 CHECK_NULL_VOID(textFieldTheme);
930 auto symbolNode = cleanNode_->GetFirstChild();
931 CHECK_NULL_VOID(symbolNode);
932 auto symbolFrameNode = AceType::DynamicCast<FrameNode>(symbolNode);
933 CHECK_NULL_VOID(symbolFrameNode);
934 auto symbolProperty = symbolFrameNode->GetLayoutProperty<TextLayoutProperty>();
935 CHECK_NULL_VOID(symbolProperty);
936 symbolProperty->UpdateFontSize(textFieldTheme->GetSymbolSize());
937 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
938 symbolProperty->UpdateFontSize(textFieldTheme->GetCancelIconSize());
939 }
940 }
941
GetSymbolDefaultSize()942 CalcDimension CleanNodeResponseArea::GetSymbolDefaultSize()
943 {
944 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
945 CHECK_NULL_RETURN(textFieldPattern, CalcDimension());
946 auto host = textFieldPattern->GetHost();
947 CHECK_NULL_RETURN(host, CalcDimension());
948 auto pipeline = host->GetContextRefPtr();
949 CHECK_NULL_RETURN(pipeline, CalcDimension());
950 auto themeManager = pipeline->GetThemeManager();
951 CHECK_NULL_RETURN(themeManager, CalcDimension());
952 auto textTheme = themeManager->GetTheme<TextTheme>();
953 CHECK_NULL_RETURN(textTheme, CalcDimension());
954 return textTheme->GetTextStyle().GetFontSize();
955 }
956
UpdateSymbolSource()957 void CleanNodeResponseArea::UpdateSymbolSource()
958 {
959 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
960 CHECK_NULL_VOID(textFieldPattern);
961 auto host = textFieldPattern->GetHost();
962 CHECK_NULL_VOID(host);
963 auto pipeline = host->GetContextRefPtr();
964 CHECK_NULL_VOID(pipeline);
965 auto themeManager = pipeline->GetThemeManager();
966 CHECK_NULL_VOID(themeManager);
967 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>(host->GetThemeScopeId());
968 CHECK_NULL_VOID(textFieldTheme);
969 auto symbolNode = cleanNode_->GetFirstChild();
970 CHECK_NULL_VOID(symbolNode);
971 auto symbolFrameNode = AceType::DynamicCast<FrameNode>(symbolNode);
972 CHECK_NULL_VOID(symbolFrameNode);
973 auto symbolProperty = symbolFrameNode->GetLayoutProperty<TextLayoutProperty>();
974 CHECK_NULL_VOID(symbolProperty);
975 auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
976 CHECK_NULL_VOID(layoutProperty);
977 auto lastFontSize = symbolProperty->GetFontSize().value_or(GetSymbolDefaultSize());
978 symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(textFieldTheme->GetCancelSymbolId()));
979 symbolProperty->UpdateSymbolColorList({ textFieldTheme->GetSymbolColor() });
980 auto maxFontScale = layoutProperty->GetMaxFontScale().value_or(MAX_FONT_SCALE);
981 symbolProperty->UpdateMaxFontScale(std::min(MAX_FONT_SCALE, maxFontScale));
982 symbolProperty->UpdateMinFontScale(layoutProperty->GetMinFontScale().value_or(0.0f));
983
984 auto iconSymbol = layoutProperty->GetCancelIconSymbol();
985 if (iconSymbol && Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
986 iconSymbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(symbolFrameNode)));
987 // reset symbol effect
988 auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
989 symbolEffectOptions.SetIsTxtActive(false);
990 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
991 }
992
993 Dimension fontSize;
994 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
995 fontSize = symbolProperty->GetFontSize().value_or(textFieldTheme->GetCancelIconSize());
996 } else {
997 fontSize = symbolProperty->GetFontSize().value_or(textFieldTheme->GetSymbolSize());
998 }
999 if (GreatOrEqualCustomPrecision(fontSize.ConvertToPx(), ICON_MAX_SIZE.ConvertToPx())) {
1000 fontSize = ICON_MAX_SIZE;
1001 }
1002 iconSize_ = fontSize;
1003 symbolProperty->UpdateFontSize(lastFontSize);
1004
1005 symbolFrameNode->MarkModifyDone();
1006 symbolFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1007 }
1008
InitClickEvent(const RefPtr<FrameNode> & frameNode)1009 void CleanNodeResponseArea::InitClickEvent(const RefPtr<FrameNode>& frameNode)
1010 {
1011 auto focusHub = frameNode->GetOrCreateFocusHub();
1012 CHECK_NULL_VOID(focusHub);
1013 auto gesture = frameNode->GetOrCreateGestureEventHub();
1014 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
1015 auto cleanNode = weak.Upgrade();
1016 CHECK_NULL_VOID(cleanNode);
1017 cleanNode->OnCleanNodeClicked();
1018 };
1019 gesture->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(clickCallback)));
1020 }
1021
OnCleanNodeClicked()1022 void CleanNodeResponseArea::OnCleanNodeClicked()
1023 {
1024 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
1025 CHECK_NULL_VOID(textFieldPattern);
1026 CHECK_NULL_VOID(!textFieldPattern->IsDragging());
1027 textFieldPattern->CleanNodeResponseKeyEvent();
1028 auto host = textFieldPattern->GetHost();
1029 CHECK_NULL_VOID(host);
1030 host->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
1031 }
1032
UpdateCleanNode(bool isShow)1033 void CleanNodeResponseArea::UpdateCleanNode(bool isShow)
1034 {
1035 isShow_ = isShow;
1036 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
1037 CHECK_NULL_VOID(textFieldPattern);
1038 CHECK_NULL_VOID(cleanNode_);
1039 auto stackLayoutProperty = cleanNode_->GetLayoutProperty<LayoutProperty>();
1040 CHECK_NULL_VOID(stackLayoutProperty);
1041 auto iconNode = cleanNode_->GetFirstChild();
1042 CHECK_NULL_VOID(iconNode);
1043 auto iconFrameNode = AceType::DynamicCast<FrameNode>(iconNode);
1044 CHECK_NULL_VOID(iconFrameNode);
1045 auto iconLayoutProperty = iconFrameNode->GetLayoutProperty<LayoutProperty>();
1046 CHECK_NULL_VOID(iconLayoutProperty);
1047 if (isShow) {
1048 auto host = textFieldPattern->GetHost();
1049 CHECK_NULL_VOID(host);
1050 auto pipeline = host->GetContextRefPtr();
1051 CHECK_NULL_VOID(pipeline);
1052 auto themeManager = pipeline->GetThemeManager();
1053 CHECK_NULL_VOID(themeManager);
1054 auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
1055 CHECK_NULL_VOID(textFieldTheme);
1056 auto rightOffset = GetCancelButtonPadding(textFieldTheme);
1057 auto geometryNode = host->GetGeometryNode();
1058 CHECK_NULL_VOID(geometryNode);
1059 auto frameSize = geometryNode->GetFrameSize();
1060 auto iconSize = GetIconSize();
1061 if (!NearZero(frameSize.Height())) {
1062 iconSize = std::min(iconSize, frameSize.Height());
1063 }
1064 auto hotZoneSize = NearZero(iconSize) ? 0.0f : iconSize + rightOffset;
1065 stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(hotZoneSize), CalcLength(iconSize)));
1066 iconLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
1067 if (IsSymbolIcon()) {
1068 auto symbolProperty = iconFrameNode->GetLayoutProperty<TextLayoutProperty>();
1069 CHECK_NULL_VOID(symbolProperty);
1070 symbolProperty->UpdateFontSize(CalcDimension(iconSize));
1071 }
1072 stackLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1073 iconLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1074 } else {
1075 stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), std::nullopt));
1076 iconLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), CalcLength(0.0f)));
1077 stackLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1078 iconLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1079 }
1080 iconFrameNode->MarkModifyDone();
1081 iconFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1082 }
1083
CheckUpdateCleanNode()1084 bool CleanNodeResponseArea::CheckUpdateCleanNode()
1085 {
1086 CHECK_NULL_RETURN(cleanNode_, false);
1087 auto cleanNodeGeometryNode = cleanNode_->GetGeometryNode();
1088 CHECK_NULL_RETURN(cleanNodeGeometryNode, false);
1089 auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
1090 CHECK_NULL_RETURN(textFieldPattern, false);
1091 auto host = textFieldPattern->GetHost();
1092 CHECK_NULL_RETURN(host, false);
1093 auto geometryNode = host->GetGeometryNode();
1094 CHECK_NULL_RETURN(geometryNode, false);
1095 auto textFieldFrameSize = geometryNode->GetFrameSize();
1096 auto cleanNodeFrameSize = cleanNodeGeometryNode->GetFrameSize();
1097 return GreatNotEqual(cleanNodeFrameSize.Height(), textFieldFrameSize.Height());
1098 }
1099
ClearArea()1100 void CleanNodeResponseArea::ClearArea()
1101 {
1102 auto hostPattern = hostPattern_.Upgrade();
1103 CHECK_NULL_VOID(hostPattern);
1104 auto host = hostPattern->GetHost();
1105 CHECK_NULL_VOID(host);
1106 CHECK_NULL_VOID(cleanNode_);
1107 host->RemoveChildAndReturnIndex(cleanNode_);
1108 cleanNode_.Reset();
1109 areaRect_.Reset();
1110 }
1111
Refresh()1112 void CleanNodeResponseArea::Refresh()
1113 {
1114 auto textFieldPattern = hostPattern_.Upgrade();
1115 if (textFieldPattern && cleanNode_) {
1116 auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
1117 auto stackLayoutProperty = cleanNode_->GetLayoutProperty<LayoutProperty>();
1118 if (layoutProperty && stackLayoutProperty) {
1119 stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
1120 }
1121 }
1122
1123 // update node symbol
1124 if (IsShowSymbol() && IsSymbolIcon() && SystemProperties::IsNeedSymbol()) {
1125 UpdateSymbolSource();
1126 return;
1127 }
1128
1129 // update node image
1130 if (!IsShowSymbol() && !IsSymbolIcon()) {
1131 LoadingImageProperty();
1132 auto info = CreateImageSourceInfo();
1133 CHECK_NULL_VOID(cleanNode_);
1134 auto imageNode = cleanNode_->GetFirstChild();
1135 CHECK_NULL_VOID(imageNode);
1136 auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
1137 CHECK_NULL_VOID(imageFrameNode);
1138 auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
1139 CHECK_NULL_VOID(imageLayoutProperty);
1140 imageLayoutProperty->UpdateImageSourceInfo(info);
1141 imageFrameNode->MarkModifyDone();
1142 imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1143 return;
1144 }
1145
1146 ReplaceNode();
1147 }
1148
ReplaceNode()1149 void CleanNodeResponseArea::ReplaceNode()
1150 {
1151 CHECK_NULL_VOID(cleanNode_);
1152 CHECK_NULL_VOID(cleanNode_->GetFirstChild());
1153 auto oldFrameNode = AceType::DynamicCast<FrameNode>(cleanNode_->GetFirstChild());
1154 CHECK_NULL_VOID(oldFrameNode);
1155
1156 if (IsShowSymbol() && SystemProperties::IsNeedSymbol()) {
1157 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
1158 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
1159 CHECK_NULL_VOID(symbolNode);
1160 cleanNode_->ReplaceChild(oldFrameNode, symbolNode);
1161 UpdateSymbolSource();
1162 return;
1163 }
1164
1165 LoadingImageProperty();
1166 auto info = CreateImageSourceInfo();
1167 auto imageNode = CreateResponseAreaImageNode(info, ImageFit::COVER, CalcSize(CalcLength(0.0f), CalcLength(0.0f)));
1168 CHECK_NULL_VOID(imageNode);
1169
1170 cleanNode_->ReplaceChild(oldFrameNode, imageNode);
1171 imageNode->MarkModifyDone();
1172 imageNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1173 }
1174
LoadingImageProperty()1175 void CleanNodeResponseArea::LoadingImageProperty()
1176 {
1177 auto pattern = hostPattern_.Upgrade();
1178 CHECK_NULL_VOID(pattern);
1179 auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
1180 CHECK_NULL_VOID(textFieldLayoutProperty);
1181 if (textFieldLayoutProperty->HasIconSize()) {
1182 auto iconSizeValue = textFieldLayoutProperty->GetIconSizeValue();
1183 if (iconSizeValue.Unit() == DimensionUnit::PERCENT) {
1184 iconSize_ = iconSizeValue;
1185 } else {
1186 auto host = pattern->GetHost();
1187 CHECK_NULL_VOID(host);
1188 auto pipeline = host->GetContext();
1189 CHECK_NULL_VOID(pipeline);
1190 auto maxFontScale = pipeline->GetFontScale();
1191 auto minFontScale = 0.0f;
1192 if (textFieldLayoutProperty->HasMaxFontScale()) {
1193 maxFontScale = std::min(textFieldLayoutProperty->GetMaxFontScale().value(), maxFontScale);
1194 }
1195 if (textFieldLayoutProperty->HasMinFontScale()) {
1196 minFontScale = textFieldLayoutProperty->GetMinFontScale().value();
1197 }
1198 iconSize_ = Dimension(iconSizeValue).ConvertToPxDistribute(minFontScale, maxFontScale);
1199 }
1200 }
1201 if (textFieldLayoutProperty->HasIconSrc()) {
1202 iconSrc_ = textFieldLayoutProperty->GetIconSrcValue();
1203 }
1204 LoadingCancelButtonColor();
1205 if (textFieldLayoutProperty->HasBundleName()) {
1206 bundleName_ = textFieldLayoutProperty->GetBundleNameValue();
1207 }
1208 if (textFieldLayoutProperty->HasModuleName()) {
1209 moduleName_ = textFieldLayoutProperty->GetModuleNameValue();
1210 }
1211 }
1212
LoadingCancelButtonColor()1213 void CleanNodeResponseArea::LoadingCancelButtonColor()
1214 {
1215 auto pattern = hostPattern_.Upgrade();
1216 CHECK_NULL_VOID(pattern);
1217 auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
1218 CHECK_NULL_VOID(textFieldLayoutProperty);
1219 if (textFieldLayoutProperty->GetIsDisabledValue(false)) {
1220 auto host = pattern->GetHost();
1221 CHECK_NULL_VOID(host);
1222 auto pipeline = host->GetContext();
1223 CHECK_NULL_VOID(pipeline);
1224 auto theme = pipeline->GetTheme<TextFieldTheme>(host->GetThemeScopeId());
1225 CHECK_NULL_VOID(theme);
1226 iconColor_ = theme->GetTextColorDisable();
1227 } else if (textFieldLayoutProperty->HasIconColor()) {
1228 iconColor_ = textFieldLayoutProperty->GetIconColorValue();
1229 }
1230 }
1231
CreateImageSourceInfo()1232 ImageSourceInfo CleanNodeResponseArea::CreateImageSourceInfo()
1233 {
1234 ImageSourceInfo info;
1235 info.SetBundleName(bundleName_);
1236 info.SetModuleName(moduleName_);
1237 if (iconSrc_.empty()) {
1238 info.SetResourceId(InternalResource::ResourceId::CLOSE_SVG);
1239 } else {
1240 info.SetSrc(iconSrc_);
1241 }
1242 auto pattern = hostPattern_.Upgrade();
1243 CHECK_NULL_RETURN(pattern, info);
1244 auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
1245 CHECK_NULL_RETURN(textFieldLayoutProperty, info);
1246 if (info.IsSvg() && textFieldLayoutProperty->HasIconColor()) {
1247 info.SetFillColor(iconColor_);
1248 CHECK_NULL_RETURN(cleanNode_, info);
1249 auto imageNode = cleanNode_->GetFirstChild();
1250 CHECK_NULL_RETURN(imageNode, info);
1251 auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
1252 CHECK_NULL_RETURN(imageFrameNode, info);
1253 auto imageRenderProperty = imageFrameNode->GetPaintProperty<ImageRenderProperty>();
1254 CHECK_NULL_RETURN(imageRenderProperty, info);
1255 imageRenderProperty->UpdateSvgFillColor(iconColor_);
1256 }
1257 return info;
1258 }
1259 } // namespace OHOS::Ace::NG