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