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_ng/event/input_event.h"
27 #include "core/components_ng/layout/layout_property.h"
28 #include "core/components_ng/pattern/image/image_pattern.h"
29 #include "core/components_ng/pattern/stack/stack_pattern.h"
30 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
31 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
32 #include "core/components_ng/property/measure_property.h"
33 #include "core/components_v2/inspector/inspector_constants.h"
34 #include "core/event/mouse_event.h"
35 #include "core/pipeline/pipeline_context.h"
36 #include "core/pipeline_ng/ui_task_scheduler.h"
37 
38 namespace OHOS::Ace::NG {
39 // TextInputResponseArea begin
LayoutChild(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)40 void TextInputResponseArea::LayoutChild(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
41 {
42     auto frameNode = layoutWrapper->GetHostNode();
43     CHECK_NULL_VOID(frameNode);
44     auto children = frameNode->GetChildren();
45     CHECK_NULL_VOID(!children.empty());
46     auto pattern = frameNode->GetPattern<TextFieldPattern>();
47     CHECK_NULL_VOID(pattern);
48     auto textInputGeometryNode = layoutWrapper->GetGeometryNode();
49     CHECK_NULL_VOID(textInputGeometryNode);
50     auto contentRect = textInputGeometryNode->GetContentRect();
51     auto textInputFrameSize = textInputGeometryNode->GetFrameSize();
52     auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
53     CHECK_NULL_VOID(childWrapper);
54     auto childGeometryNode = childWrapper->GetGeometryNode();
55     CHECK_NULL_VOID(childGeometryNode);
56     auto childFrameSize = childGeometryNode->GetFrameSize();
57     auto childOffset = GetChildOffset(textInputFrameSize, contentRect, childFrameSize, nodeWidth);
58     childGeometryNode->SetFrameOffset(childOffset);
59     childWrapper->GetGeometryNode()->SetFrameSize(childFrameSize);
60     areaRect_.SetSize(childFrameSize);
61     areaRect_.SetOffset(childOffset);
62     childWrapper->Layout();
63     nodeWidth += childFrameSize.Width();
64 }
65 
GetChildOffset(SizeF parentSize,RectF contentRect,SizeF childSize,float nodeWidth)66 OffsetF TextInputResponseArea::GetChildOffset(SizeF parentSize, RectF contentRect, SizeF childSize, float nodeWidth)
67 {
68     auto offset = Alignment::GetAlignPosition(parentSize, childSize, Alignment::CENTER);
69     auto textFieldPattern = hostPattern_.Upgrade();
70     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
71     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
72     if (isRTL) {
73         return OffsetF(nodeWidth, offset.GetY());
74     } else {
75         return OffsetF(parentSize.Width() - childSize.Width() - nodeWidth, offset.GetY());
76     }
77 }
78 
Measure(LayoutWrapper * layoutWrapper,int32_t index)79 SizeF TextInputResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
80 {
81     auto childWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
82     auto textfieldLayoutProperty = AceType::DynamicCast<TextFieldLayoutProperty>(layoutWrapper->GetLayoutProperty());
83     SizeF size(0, 0);
84     CHECK_NULL_RETURN(textfieldLayoutProperty, size);
85     auto childLayoutConstraint = textfieldLayoutProperty->CreateChildConstraint();
86     CHECK_NULL_RETURN(childWrapper, size);
87     auto childLayoutProperty = childWrapper->GetLayoutProperty();
88     childWrapper->Measure(childLayoutConstraint);
89     auto geometryNode = childWrapper->GetGeometryNode();
90     CHECK_NULL_RETURN(geometryNode, size);
91     return geometryNode->GetFrameSize();
92 }
93 
GetFrameSize(bool withSafeArea)94 SizeF TextInputResponseArea::GetFrameSize(bool withSafeArea)
95 {
96     auto frameNode = GetFrameNode();
97     CHECK_NULL_RETURN(frameNode, SizeF(0, 0));
98     auto geometryNode = frameNode->GetGeometryNode();
99     CHECK_NULL_RETURN(geometryNode, SizeF(0, 0));
100     return geometryNode->GetFrameSize(withSafeArea);
101 }
102 
GetStackAlignment(const TextDirection & userDirection)103 Alignment TextInputResponseArea::GetStackAlignment(const TextDirection& userDirection)
104 {
105     bool isSysRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
106     if ((isSysRtl && userDirection == TextDirection::LTR) ||
107         (!isSysRtl && userDirection == TextDirection::RTL)) {
108         return Alignment::CENTER_RIGHT;
109     }
110     return Alignment::CENTER_LEFT;
111 }
112 // TextInputResponseArea end
113 
114 // PasswordResponseArea begin
InitResponseArea()115 void PasswordResponseArea::InitResponseArea()
116 {
117     ClearArea();
118     auto pattern = hostPattern_.Upgrade();
119     CHECK_NULL_VOID(pattern);
120     auto host = pattern->GetHost();
121     CHECK_NULL_VOID(host);
122     if (!IsShowPasswordIcon()) {
123         return;
124     }
125     auto passwordNode = CreateNode();
126     CHECK_NULL_VOID(passwordNode);
127     passwordNode->MountToParent(host);
128 }
129 
GetFrameNode()130 const RefPtr<FrameNode> PasswordResponseArea::GetFrameNode()
131 {
132     auto frameNode = passwordNode_.Upgrade();
133     CHECK_NULL_RETURN(frameNode, nullptr);
134     auto stackNode = frameNode->GetParent();
135     CHECK_NULL_RETURN(stackNode, nullptr);
136     auto ret = AceType::DynamicCast<FrameNode>(stackNode);
137     CHECK_NULL_RETURN(ret, nullptr);
138     return ret;
139 }
140 
CreateNode()141 RefPtr<FrameNode> PasswordResponseArea::CreateNode()
142 {
143     auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
144     CHECK_NULL_RETURN(textFieldPattern, nullptr);
145     auto iconSize = GetIconSize();
146     auto rightOffset = GetIconRightOffset();
147     auto hotZoneSize = iconSize + rightOffset;
148 
149     auto stackNode = FrameNode::CreateFrameNode(
150         V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
151     auto stackLayoutProperty = stackNode->GetLayoutProperty<LayoutProperty>();
152     CHECK_NULL_RETURN(stackLayoutProperty, nullptr);
153     stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(hotZoneSize), std::nullopt));
154     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
155     CHECK_NULL_RETURN(layoutProperty, nullptr);
156     stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
157     AddEvent(stackNode);
158     stackNode->MarkModifyDone();
159 
160     auto imageNode = FrameNode::CreateFrameNode(
161         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
162     imageNode->SetDraggable(false);
163     LoadImageSourceInfo();
164     auto currentImageSourceInfo = GetCurrentSourceInfo();
165     CHECK_NULL_RETURN(currentImageSourceInfo, nullptr);
166     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
167     imageLayoutProperty->UpdateImageSourceInfo(currentImageSourceInfo.value());
168     imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
169     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
170     auto eventHub = imageNode->GetEventHub<ImageEventHub>();
171     CHECK_NULL_RETURN(eventHub, nullptr);
172     eventHub->SetOnError([ weakNode = WeakClaim(AceType::RawPtr(imageNode)), weakArea = WeakClaim(this) ]
173         (const LoadImageFailEvent& info) {
174         auto host = weakNode.Upgrade();
175         CHECK_NULL_VOID(host);
176         auto area = weakArea.Upgrade();
177         CHECK_NULL_VOID(area);
178         auto imagePattern = host->GetPattern<ImagePattern>();
179         CHECK_NULL_VOID(imagePattern);
180         auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
181         layoutProperty->UpdateImageSourceInfo(area->GetDefaultSourceInfo(area->isObscured_));
182         imagePattern->LoadImageDataIfNeed();
183     });
184     imageNode->MarkModifyDone();
185     imageNode->MountToParent(stackNode);
186     passwordNode_ = imageNode;
187     stackNode_ = stackNode;
188     return stackNode;
189 }
190 
AddEvent(const RefPtr<FrameNode> & node)191 void PasswordResponseArea::AddEvent(const RefPtr<FrameNode>& node)
192 {
193     CHECK_NULL_VOID(node);
194     auto focusHub = node->GetOrCreateFocusHub();
195     CHECK_NULL_VOID(focusHub);
196     auto gesture = node->GetOrCreateGestureEventHub();
197     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
198         auto button = weak.Upgrade();
199         CHECK_NULL_VOID(button);
200         button->OnPasswordIconClicked();
201         auto context = PipelineBase::GetCurrentContextSafely();
202         CHECK_NULL_VOID(context);
203         auto theme = context->GetTheme<TextFieldTheme>();
204         CHECK_NULL_VOID(theme);
205         auto node = button->GetFrameNode();
206         CHECK_NULL_VOID(node);
207         auto message = !button->IsObscured() ? theme->GetHasShowedPassword() : theme->GetHasHiddenPassword();
208         node->OnAccessibilityEvent(AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY, message);
209     };
210     auto mouseTask = [id = Container::CurrentId(), weak = hostPattern_](MouseInfo& info) {
211         info.SetStopPropagation(true);
212         auto pattern = weak.Upgrade();
213         CHECK_NULL_VOID(pattern);
214         auto textfield = DynamicCast<TextFieldPattern>(pattern);
215         CHECK_NULL_VOID(textfield);
216         textfield->RestoreDefaultMouseState();
217     };
218     auto touchTask = [weak = WeakClaim(this)](TouchEventInfo& info) {
219         info.SetStopPropagation(true);
220     };
221 
222     auto inputHub = node->GetOrCreateInputEventHub();
223     auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseTask));
224     inputHub->AddOnMouseEvent(mouseEvent);
225     gesture->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(clickCallback)));
226     gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
227 }
228 
Refresh()229 void PasswordResponseArea::Refresh()
230 {
231     auto imageNode = passwordNode_.Upgrade();
232     if (!imageNode) {
233         InitResponseArea();
234         return;
235     }
236 
237     auto textFieldPattern = hostPattern_.Upgrade();
238     if (textFieldPattern && stackNode_) {
239         auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
240         auto stackLayoutProperty = stackNode_->GetLayoutProperty<LayoutProperty>();
241         if (stackLayoutProperty && layoutProperty) {
242             stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
243         }
244     }
245 
246     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
247     CHECK_NULL_VOID(imageLayoutProperty);
248     auto currentSrc = imageLayoutProperty->GetImageSourceInfoValue().GetSrc();
249     LoadImageSourceInfo();
250     auto src = isObscured_ ? hideIcon_->GetSrc() : showIcon_->GetSrc();
251     if (currentSrc != src) {
252         UpdateImageSource();
253     }
254 }
255 
OnPasswordIconClicked()256 void PasswordResponseArea::OnPasswordIconClicked()
257 {
258     isObscured_ = !isObscured_;
259     ChangeObscuredState();
260 }
261 
ChangeObscuredState()262 void PasswordResponseArea::ChangeObscuredState()
263 {
264     UpdateImageSource();
265     auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
266     CHECK_NULL_VOID(textFieldPattern);
267     textFieldPattern->OnObscuredChanged(isObscured_);
268 }
269 
Measure(LayoutWrapper * layoutWrapper,int32_t index)270 SizeF PasswordResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
271 {
272     if (!IsShowPasswordIcon()) {
273         return SizeF(0, 0);
274     }
275     return TextInputResponseArea::Measure(layoutWrapper, index);
276 }
277 
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)278 void PasswordResponseArea::Layout(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
279 {
280     if (!IsShowPasswordIcon()) {
281         return;
282     }
283     LayoutChild(layoutWrapper, index, nodeWidth);
284 }
285 
GetIconSize()286 float PasswordResponseArea::GetIconSize()
287 {
288     auto textFieldPattern = hostPattern_.Upgrade();
289     CHECK_NULL_RETURN(textFieldPattern, 0.0f);
290     auto tmpHost = textFieldPattern->GetHost();
291     CHECK_NULL_RETURN(tmpHost, 0.0f);
292     auto pipeline = tmpHost->GetContextRefPtr();
293     CHECK_NULL_RETURN(pipeline, 0.0f);
294     auto themeManager = pipeline->GetThemeManager();
295     CHECK_NULL_RETURN(themeManager, 0.0f);
296     auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
297     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
298     return static_cast<float>(textFieldTheme->GetIconSize().ConvertToPx());
299 }
300 
GetIconRightOffset()301 float PasswordResponseArea::GetIconRightOffset()
302 {
303     auto textFieldPattern = hostPattern_.Upgrade();
304     CHECK_NULL_RETURN(textFieldPattern, 0.0f);
305     auto tmpHost = textFieldPattern->GetHost();
306     auto pipeline = tmpHost->GetContextRefPtr();
307     CHECK_NULL_RETURN(pipeline, 0.0f);
308     auto themeManager = pipeline->GetThemeManager();
309     CHECK_NULL_RETURN(themeManager, 0.0f);
310     auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
311     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
312     auto themePadding = textFieldTheme->GetPadding();
313     return static_cast<float>(themePadding.Left().ConvertToPx());
314 }
315 
LoadImageSourceInfo()316 void PasswordResponseArea::LoadImageSourceInfo()
317 {
318     auto textFieldPattern = hostPattern_.Upgrade();
319     CHECK_NULL_VOID(textFieldPattern);
320     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
321     CHECK_NULL_VOID(layoutProperty);
322     showIcon_ = layoutProperty->GetShowPasswordSourceInfoValue(GetDefaultSourceInfo(false));
323     hideIcon_ = layoutProperty->GetHidePasswordSourceInfoValue(GetDefaultSourceInfo(true));
324     auto tmpHost = textFieldPattern->GetHost();
325     CHECK_NULL_VOID(tmpHost);
326     auto pipeline = tmpHost->GetContextRefPtr();
327     CHECK_NULL_VOID(pipeline);
328     auto themeManager = pipeline->GetThemeManager();
329     CHECK_NULL_VOID(themeManager);
330     auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
331     CHECK_NULL_VOID(textFieldTheme);
332     if (showIcon_->GetResourceId() == InternalResource::ResourceId::SHOW_PASSWORD_SVG) {
333         showIcon_->SetFillColor(textFieldTheme->GetTextColor());
334     }
335     if (hideIcon_->GetResourceId() == InternalResource::ResourceId::HIDE_PASSWORD_SVG) {
336         hideIcon_->SetFillColor(textFieldTheme->GetTextColor());
337     }
338     if (layoutProperty->GetIsDisabledValue(false)) {
339         auto iconTheme = pipeline->GetTheme<IconTheme>();
340         CHECK_NULL_VOID(iconTheme);
341         auto textDisableColor = textFieldTheme->GetTextColorDisable();
342         auto hideIconPath = iconTheme->GetIconPath(hideIcon_->GetResourceId());
343         hideIcon_->SetSrc(hideIconPath, textDisableColor);
344         auto showIconPath = iconTheme->GetIconPath(showIcon_->GetResourceId());
345         showIcon_->SetSrc(showIconPath, textDisableColor);
346         UpdateImageSource();
347     }
348 }
349 
GetDefaultSourceInfo(bool isObscured)350 ImageSourceInfo PasswordResponseArea::GetDefaultSourceInfo(bool isObscured)
351 {
352     if (isObscured) {
353         ImageSourceInfo hideSystemSourceInfo;
354         hideSystemSourceInfo.SetResourceId(InternalResource::ResourceId::HIDE_PASSWORD_SVG);
355         return hideSystemSourceInfo;
356     }
357     ImageSourceInfo showSystemSourceInfo;
358     showSystemSourceInfo.SetResourceId(InternalResource::ResourceId::SHOW_PASSWORD_SVG);
359     return showSystemSourceInfo;
360 }
361 
UpdateImageSource()362 void PasswordResponseArea::UpdateImageSource()
363 {
364     auto frameNode = passwordNode_.Upgrade();
365     CHECK_NULL_VOID(frameNode);
366     auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
367     CHECK_NULL_VOID(layoutProperty);
368     auto currentImageSourceInfo = GetCurrentSourceInfo();
369     CHECK_NULL_VOID(currentImageSourceInfo);
370     layoutProperty->UpdateImageSourceInfo(currentImageSourceInfo.value());
371     auto imagePattern = frameNode->GetPattern<ImagePattern>();
372     CHECK_NULL_VOID(imagePattern);
373     imagePattern->LoadImageDataIfNeed();
374 }
375 
IsShowPasswordIcon()376 bool PasswordResponseArea::IsShowPasswordIcon()
377 {
378     auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
379     CHECK_NULL_RETURN(textFieldPattern, false);
380     return textFieldPattern->IsShowPasswordIcon();
381 } // PasswordResponseArea end
382 
383 // UnitResponseArea begin
InitResponseArea()384 void UnitResponseArea::InitResponseArea()
385 {
386     auto pattern = hostPattern_.Upgrade();
387     CHECK_NULL_VOID(pattern);
388     auto host = pattern->GetHost();
389     CHECK_NULL_VOID(host);
390     if (!IsShowUnit()) {
391         return;
392     }
393     CHECK_NULL_VOID(unitNode_);
394     unitNode_->MountToParent(host);
395 }
396 
GetFrameNode()397 const RefPtr<FrameNode> UnitResponseArea::GetFrameNode()
398 {
399     auto frameNode = AceType::DynamicCast<FrameNode>(unitNode_);
400     CHECK_NULL_RETURN(frameNode, nullptr);
401     return frameNode;
402 }
403 
Measure(LayoutWrapper * layoutWrapper,int32_t index)404 SizeF UnitResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
405 {
406     if (!IsShowUnit()) {
407         return SizeF(0, 0);
408     }
409     return TextInputResponseArea::Measure(layoutWrapper, index);
410 }
411 
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)412 void UnitResponseArea::Layout(LayoutWrapper* layoutWrapper, int32_t index, float& nodeWidth)
413 {
414     if (!IsShowUnit()) {
415         return;
416     }
417     LayoutChild(layoutWrapper, index, nodeWidth);
418 }
419 
IsShowUnit()420 bool UnitResponseArea::IsShowUnit()
421 {
422     auto pattern = hostPattern_.Upgrade();
423     CHECK_NULL_RETURN(pattern, false);
424     auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern);
425     CHECK_NULL_RETURN(textFieldPattern, false);
426     return textFieldPattern->IsUnderlineMode();
427 } // UnitResponseArea end
428 
InitResponseArea()429 void CleanNodeResponseArea::InitResponseArea()
430 {
431     auto pattern = hostPattern_.Upgrade();
432     CHECK_NULL_VOID(pattern);
433     auto host = pattern->GetHost();
434     CHECK_NULL_VOID(host);
435     LoadingImageProperty();
436     auto cleanNode = CreateNode();
437     CHECK_NULL_VOID(cleanNode);
438     cleanNode->MountToParent(host);
439 }
440 
Measure(LayoutWrapper * layoutWrapper,int32_t index)441 SizeF CleanNodeResponseArea::Measure(LayoutWrapper* layoutWrapper, int32_t index)
442 {
443     return TextInputResponseArea::Measure(layoutWrapper, index);
444 }
445 
IsShowClean()446 bool CleanNodeResponseArea::IsShowClean()
447 {
448     auto pattern = hostPattern_.Upgrade();
449     CHECK_NULL_RETURN(pattern, false);
450     auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern);
451     CHECK_NULL_RETURN(textFieldPattern, false);
452     return textFieldPattern->IsShowCancelButtonMode();
453 }
454 
Layout(LayoutWrapper * layoutWrapper,int32_t index,float & nodeWidth)455 void CleanNodeResponseArea::Layout(LayoutWrapper *layoutWrapper, int32_t index, float &nodeWidth)
456 {
457     if (!IsShowClean()) {
458         return;
459     }
460     LayoutChild(layoutWrapper, index, nodeWidth);
461 }
462 
GetFrameNode()463 const RefPtr<FrameNode> CleanNodeResponseArea::GetFrameNode()
464 {
465     return cleanNode_;
466 }
467 
CreateNode()468 RefPtr<FrameNode> CleanNodeResponseArea::CreateNode()
469 {
470     auto stackNode = FrameNode::CreateFrameNode(
471         V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
472     auto stackLayoutProperty = stackNode->GetLayoutProperty<LayoutProperty>();
473     CHECK_NULL_RETURN(stackLayoutProperty, nullptr);
474     stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), std::nullopt));
475     stackLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
476     auto textFieldPattern = hostPattern_.Upgrade();
477     CHECK_NULL_RETURN(textFieldPattern, nullptr);
478     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
479     CHECK_NULL_RETURN(layoutProperty, nullptr);
480     stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
481     stackNode->MarkModifyDone();
482     auto cleanNode = FrameNode::CreateFrameNode(
483         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
484     CHECK_NULL_RETURN(cleanNode, nullptr);
485     cleanNode->SetDraggable(false);
486     cleanNode_ = stackNode;
487     auto info = CreateImageSourceInfo();
488     auto imageLayoutProperty = cleanNode->GetLayoutProperty<ImageLayoutProperty>();
489     CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
490     imageLayoutProperty->UpdateImageSourceInfo(info);
491     imageLayoutProperty->UpdateImageFit(ImageFit::COVER);
492     imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), CalcLength(0.0f)));
493     imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
494     cleanNode->MarkModifyDone();
495     cleanNode->MountToParent(stackNode);
496     InitClickEvent(stackNode);
497     return stackNode;
498 }
499 
InitClickEvent(const RefPtr<FrameNode> & frameNode)500 void CleanNodeResponseArea::InitClickEvent(const RefPtr<FrameNode>& frameNode)
501 {
502     auto focusHub = frameNode->GetOrCreateFocusHub();
503     CHECK_NULL_VOID(focusHub);
504     auto gesture = frameNode->GetOrCreateGestureEventHub();
505     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
506         auto cleanNode = weak.Upgrade();
507         CHECK_NULL_VOID(cleanNode);
508         cleanNode->OnCleanNodeClicked();
509     };
510     gesture->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(clickCallback)));
511 }
512 
OnCleanNodeClicked()513 void CleanNodeResponseArea::OnCleanNodeClicked()
514 {
515     auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
516     CHECK_NULL_VOID(textFieldPattern);
517     CHECK_NULL_VOID(!textFieldPattern->IsDragging());
518     textFieldPattern->CleanNodeResponseKeyEvent();
519     auto host = textFieldPattern->GetHost();
520     CHECK_NULL_VOID(host);
521     host->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
522 }
523 
UpdateCleanNode(bool isShow)524 void CleanNodeResponseArea::UpdateCleanNode(bool isShow)
525 {
526     isShow_ = isShow;
527     auto textFieldPattern = DynamicCast<TextFieldPattern>(hostPattern_.Upgrade());
528     CHECK_NULL_VOID(textFieldPattern);
529     CHECK_NULL_VOID(cleanNode_);
530     auto stackLayoutProperty = cleanNode_->GetLayoutProperty<LayoutProperty>();
531     CHECK_NULL_VOID(stackLayoutProperty);
532     auto imageNode = cleanNode_->GetFirstChild();
533     CHECK_NULL_VOID(imageNode);
534     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
535     CHECK_NULL_VOID(imageFrameNode);
536     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
537     CHECK_NULL_VOID(imageLayoutProperty);
538     if (isShow) {
539         auto host = textFieldPattern->GetHost();
540         CHECK_NULL_VOID(host);
541         auto pipeline = host->GetContextRefPtr();
542         CHECK_NULL_VOID(pipeline);
543         auto themeManager = pipeline->GetThemeManager();
544         CHECK_NULL_VOID(themeManager);
545         auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
546         CHECK_NULL_VOID(textFieldTheme);
547         auto themePadding = textFieldTheme->GetPadding();
548         auto rightOffset = static_cast<float>(themePadding.Left().ConvertToPx());
549         auto geometryNode = host->GetGeometryNode();
550         CHECK_NULL_VOID(geometryNode);
551         auto frameSize = geometryNode->GetFrameSize();
552         auto iconSize = std::min(iconSize_.ConvertToPx(), static_cast<double>(frameSize.Height()));
553         if (NearZero(iconSize)) {
554             isShow_ = false;
555         }
556         auto hotZoneSize = iconSize + rightOffset;
557         stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(hotZoneSize), std::nullopt));
558         imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
559         stackLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
560         imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
561     } else {
562         stackLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), std::nullopt));
563         imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(0.0f), CalcLength(0.0f)));
564         stackLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
565         imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
566     }
567     imageFrameNode->MarkModifyDone();
568     imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
569 }
570 
ClearArea()571 void CleanNodeResponseArea::ClearArea()
572 {
573     auto hostPattern = hostPattern_.Upgrade();
574     CHECK_NULL_VOID(hostPattern);
575     auto host = hostPattern->GetHost();
576     CHECK_NULL_VOID(host);
577     CHECK_NULL_VOID(cleanNode_);
578     host->RemoveChildAndReturnIndex(cleanNode_);
579     cleanNode_.Reset();
580     areaRect_.Reset();
581 }
582 
Refresh()583 void CleanNodeResponseArea::Refresh()
584 {
585     auto textFieldPattern = hostPattern_.Upgrade();
586     if (textFieldPattern && cleanNode_) {
587         auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
588         auto stackLayoutProperty = cleanNode_->GetLayoutProperty<LayoutProperty>();
589         if (layoutProperty && stackLayoutProperty) {
590             stackLayoutProperty->UpdateAlignment(GetStackAlignment(layoutProperty->GetLayoutDirection()));
591         }
592     }
593     LoadingImageProperty();
594     auto info = CreateImageSourceInfo();
595     CHECK_NULL_VOID(cleanNode_);
596     auto imageNode = cleanNode_->GetFirstChild();
597     CHECK_NULL_VOID(imageNode);
598     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
599     CHECK_NULL_VOID(imageFrameNode);
600     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
601     CHECK_NULL_VOID(imageLayoutProperty);
602     imageLayoutProperty->UpdateImageSourceInfo(info);
603     imageFrameNode->MarkModifyDone();
604     imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
605 }
606 
LoadingImageProperty()607 void CleanNodeResponseArea::LoadingImageProperty()
608 {
609     auto pattern = hostPattern_.Upgrade();
610     CHECK_NULL_VOID(pattern);
611     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
612     CHECK_NULL_VOID(textFieldLayoutProperty);
613     if (textFieldLayoutProperty->HasIconSize()) {
614         iconSize_ = textFieldLayoutProperty->GetIconSizeValue();
615     }
616     if (textFieldLayoutProperty->HasIconSrc()) {
617         iconSrc_ = textFieldLayoutProperty->GetIconSrcValue();
618     }
619     LoadingCancelButtonColor();
620     if (textFieldLayoutProperty->HasBundleName()) {
621         bundleName_ = textFieldLayoutProperty->GetBundleNameValue();
622     }
623     if (textFieldLayoutProperty->HasModuleName()) {
624         moduleName_ = textFieldLayoutProperty->GetModuleNameValue();
625     }
626 }
627 
LoadingCancelButtonColor()628 void CleanNodeResponseArea::LoadingCancelButtonColor()
629 {
630     auto pattern = hostPattern_.Upgrade();
631     CHECK_NULL_VOID(pattern);
632     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
633     CHECK_NULL_VOID(textFieldLayoutProperty);
634     if (textFieldLayoutProperty->GetIsDisabledValue(false)) {
635         auto host = pattern->GetHost();
636         CHECK_NULL_VOID(host);
637         auto pipeline = host->GetContext();
638         CHECK_NULL_VOID(pipeline);
639         auto theme = pipeline->GetTheme<TextFieldTheme>();
640         CHECK_NULL_VOID(theme);
641         iconColor_ = theme->GetTextColorDisable();
642     } else if (textFieldLayoutProperty->HasIconColor()) {
643         iconColor_ = textFieldLayoutProperty->GetIconColorValue();
644     }
645 }
646 
CreateImageSourceInfo()647 ImageSourceInfo CleanNodeResponseArea::CreateImageSourceInfo()
648 {
649     ImageSourceInfo info;
650     info.SetBundleName(bundleName_);
651     info.SetModuleName(moduleName_);
652     if (iconSrc_.empty()) {
653         info.SetResourceId(InternalResource::ResourceId::CLOSE_SVG);
654     } else {
655         info.SetSrc(iconSrc_);
656     }
657     auto pattern = hostPattern_.Upgrade();
658     CHECK_NULL_RETURN(pattern, info);
659     auto textFieldLayoutProperty = pattern->GetLayoutProperty<TextFieldLayoutProperty>();
660     CHECK_NULL_RETURN(textFieldLayoutProperty, info);
661     if (info.IsSvg() && textFieldLayoutProperty->HasIconColor()) {
662         info.SetFillColor(iconColor_);
663         CHECK_NULL_RETURN(cleanNode_, info);
664         auto imageNode = cleanNode_->GetFirstChild();
665         CHECK_NULL_RETURN(imageNode, info);
666         auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
667         CHECK_NULL_RETURN(imageFrameNode, info);
668         auto imageRenderProperty = imageFrameNode->GetPaintProperty<ImageRenderProperty>();
669         CHECK_NULL_RETURN(imageRenderProperty, info);
670         imageRenderProperty->UpdateSvgFillColor(iconColor_);
671     }
672     return info;
673 }
674 } // namespace OHOS::Ace::NG