1 /*
2  * Copyright (c) 2022-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 #include "core/components_ng/pattern/bubble/bubble_view.h"
16 
17 #include "base/geometry/dimension.h"
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/memory/ace_type.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/utils.h"
22 #include "core/common/container.h"
23 #include "core/components/button/button_theme.h"
24 #include "core/components/common/layout/constants.h"
25 #include "core/components/common/layout/grid_system_manager.h"
26 #include "core/components/common/properties/alignment.h"
27 #include "core/components/common/properties/color.h"
28 #include "core/components/popup/popup_theme.h"
29 #include "core/components_ng/base/frame_node.h"
30 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
31 #include "core/components_ng/pattern/button/button_event_hub.h"
32 #include "core/components_ng/pattern/button/button_layout_property.h"
33 #include "core/components_ng/pattern/button/button_pattern.h"
34 #include "core/components_ng/pattern/flex/flex_layout_pattern.h"
35 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
36 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
37 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
38 #include "core/components_ng/pattern/text/text_pattern.h"
39 #include "core/components_ng/property/calc_length.h"
40 #include "core/components_ng/render/paint_property.h"
41 #include "core/components_v2/inspector/inspector_constants.h"
42 #include "core/pipeline/base/element_register.h"
43 #include "core/pipeline/pipeline_base.h"
44 #include "core/pipeline_ng/pipeline_context.h"
45 
46 namespace OHOS::Ace::NG {
47 namespace {
48 constexpr double DOUBLENESS = 2.0;
49 constexpr Dimension OUT_RANGE_SPACE = 40.0_vp;
50 constexpr Dimension MIN_BUTTON_FONT_SIZE = 9.0_vp;
51 constexpr int32_t BUTTON_MAX_LINE = 2;
52 constexpr float AGE_FONT_MAX_SIZE_SCALE = 2.0f;
53 constexpr float AGE_SCALE_NUMBER = 1.0f;
54 constexpr float AGE_BUTTONS_LAYOUT_HEIGHT_RATE = 15.0f;
55 
GetDisplayWindowRectOffset()56 OffsetF GetDisplayWindowRectOffset()
57 {
58     auto pipelineContext = PipelineContext::GetCurrentContext();
59     CHECK_NULL_RETURN(pipelineContext, OffsetF());
60     auto overlayManager = pipelineContext->GetOverlayManager();
61     CHECK_NULL_RETURN(overlayManager, OffsetF());
62     auto displayWindowOffset = OffsetF(pipelineContext->GetDisplayWindowRectInfo().GetOffset().GetX(),
63         pipelineContext->GetDisplayWindowRectInfo().GetOffset().GetY());
64     return displayWindowOffset;
65 }
66 
GetPopupTheme()67 RefPtr<PopupTheme> GetPopupTheme()
68 {
69     auto pipeline = PipelineBase::GetCurrentContext();
70     CHECK_NULL_RETURN(pipeline, nullptr);
71     auto popupTheme = pipeline->GetTheme<PopupTheme>();
72     CHECK_NULL_RETURN(popupTheme, nullptr);
73     return popupTheme;
74 }
75 
GetMaxWith()76 Dimension GetMaxWith()
77 {
78     auto gridColumnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::BUBBLE_TYPE);
79     auto parent = gridColumnInfo->GetParent();
80     if (parent) {
81         parent->BuildColumnWidth();
82     }
83     auto maxWidth = Dimension(gridColumnInfo->GetMaxWidth());
84     return maxWidth;
85 }
86 
GetAgeFontSize(const std::optional<Dimension> & originalFontSize)87 Dimension GetAgeFontSize(const std::optional<Dimension>& originalFontSize)
88 {
89     auto fontSize = Dimension(originalFontSize->Value(), originalFontSize->Unit());
90     auto pipeline = PipelineBase::GetCurrentContext();
91     CHECK_NULL_RETURN(pipeline, fontSize);
92     auto fontSizeScale = pipeline->GetFontScale();
93     auto fontScale = fontSizeScale > AGE_FONT_MAX_SIZE_SCALE ? AGE_FONT_MAX_SIZE_SCALE : fontSizeScale;
94     fontSize.SetValue((originalFontSize->Value()) * fontScale);
95     return fontSize;
96 }
97 
UpdateTextProperties(const RefPtr<PopupParam> & param,const RefPtr<TextLayoutProperty> & textLayoutProps)98 void UpdateTextProperties(const RefPtr<PopupParam>& param, const RefPtr<TextLayoutProperty>& textLayoutProps)
99 {
100     auto textColor = param->GetTextColor();
101     if (textColor.has_value()) {
102         textLayoutProps->UpdateTextColor(textColor.value());
103     }
104     auto fontSize = param->GetFontSize();
105     if (fontSize.has_value()) {
106         if (!param->IsUseCustom()) {
107             textLayoutProps->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
108             textLayoutProps->UpdateFontSize(fontSize.value());
109         } else {
110             textLayoutProps->UpdateFontSize(fontSize.value());
111         }
112     }
113     auto fontWeight = param->GetFontWeight();
114     if (fontWeight.has_value()) {
115         textLayoutProps->UpdateFontWeight(fontWeight.value());
116     }
117     auto fontStyle = param->GetFontStyle();
118     if (fontStyle.has_value()) {
119         textLayoutProps->UpdateItalicFontStyle(fontStyle.value());
120     }
121 }
122 } // namespace
123 
SetHitTestMode(RefPtr<FrameNode> & popupNode,bool isBlockEvent)124 void SetHitTestMode(RefPtr<FrameNode>& popupNode, bool isBlockEvent)
125 {
126     auto hub = popupNode->GetEventHub<BubbleEventHub>();
127     if (hub) {
128         auto ges = hub->GetOrCreateGestureEventHub();
129         if (!isBlockEvent) {
130             ges->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
131         } else {
132             ges->SetHitTestMode(HitTestMode::HTMDEFAULT);
133         }
134     }
135 }
136 
CreateBubbleNode(const std::string & targetTag,int32_t targetId,const RefPtr<PopupParam> & param)137 RefPtr<FrameNode> BubbleView::CreateBubbleNode(
138     const std::string& targetTag, int32_t targetId, const RefPtr<PopupParam>& param)
139 {
140     auto popupId = ElementRegister::GetInstance()->MakeUniqueId();
141     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::POPUP_ETS_TAG, popupId);
142     auto popupNode =
143         FrameNode::CreateFrameNode(V2::POPUP_ETS_TAG, popupId, AceType::MakeRefPtr<BubblePattern>(targetId, targetTag));
144     auto popupProp = AceType::DynamicCast<BubbleLayoutProperty>(popupNode->GetLayoutProperty());
145     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
146     auto useCustom = param->IsUseCustom();
147 
148     // onstateChange.
149     auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
150     if (bubbleHub) {
151         bubbleHub->SetOnStateChange(param->GetOnStateChange());
152     }
153 
154     auto message = param->GetMessage();
155     auto primaryButton = param->GetPrimaryButtonProperties();
156     auto secondaryButton = param->GetSecondaryButtonProperties();
157     // Update props
158     popupProp->UpdateUseCustom(useCustom);
159     popupProp->UpdateEnableArrow(param->EnableArrow());
160     popupProp->UpdatePlacement(param->GetPlacement());
161     popupProp->UpdateShowInSubWindow(param->IsShowInSubWindow());
162     popupProp->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
163     popupProp->UpdateBlockEvent(param->IsBlockEvent());
164     popupProp->UpdateIsCaretMode(param->IsCaretMode());
165     if (param->GetArrowHeight().has_value()) {
166         popupProp->UpdateArrowHeight(param->GetArrowHeight().value());
167     }
168     if (param->GetArrowWidth().has_value()) {
169         popupProp->UpdateArrowWidth(param->GetArrowWidth().value());
170     }
171     if (param->GetRadius().has_value()) {
172         popupProp->UpdateRadius(param->GetRadius().value());
173     }
174     popupProp->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
175     SetHitTestMode(popupNode, param->IsBlockEvent());
176     if (param->GetTargetSpace().has_value()) {
177         popupProp->UpdateTargetSpace(param->GetTargetSpace().value());
178     }
179     auto displayWindowOffset = GetDisplayWindowRectOffset();
180     popupProp->UpdateDisplayWindowOffset(displayWindowOffset);
181     popupPaintProp->UpdateEnableArrow(param->EnableArrow());
182     if (param->GetArrowOffset().has_value()) {
183         popupPaintProp->UpdateArrowOffset(param->GetArrowOffset().value());
184     }
185     if (param->IsMaskColorSetted()) {
186         popupPaintProp->UpdateMaskColor(param->GetMaskColor());
187     }
188     if (param->IsBackgroundColorSetted()) {
189         popupPaintProp->UpdateBackgroundColor(param->GetBackgroundColor());
190     }
191     popupPaintProp->UpdateAutoCancel(!param->HasAction());
192     popupPaintProp->UpdatePlacement(param->GetPlacement());
193     if (param->GetHasTransition()) {
194         popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
195     }
196 
197     auto bubbleAccessibilityProperty = popupNode->GetAccessibilityProperty<AccessibilityProperty>();
198     CHECK_NULL_RETURN(bubbleAccessibilityProperty, nullptr);
199     bubbleAccessibilityProperty->SetText(message);
200     auto bubblePattern = popupNode->GetPattern<BubblePattern>();
201     auto textColor = param->GetTextColor();
202     bubblePattern->SetMessageColor(textColor.has_value());
203     bubblePattern->SetHasTransition(param->GetHasTransition());
204     // Create child
205     RefPtr<FrameNode> child;
206     if (primaryButton.showButton || secondaryButton.showButton) {
207         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
208             AceType::MakeRefPtr<LinearLayoutPattern>(true));
209         auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
210         columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
211         columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
212         auto combinedChild = CreateCombinedChild(param, popupId, targetId, popupNode);
213         popupPaintProp->UpdatePrimaryButtonShow(primaryButton.showButton);
214         popupPaintProp->UpdateSecondaryButtonShow(secondaryButton.showButton);
215         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
216             popupPaintProp->UpdateAutoCancel(false);
217         }
218         combinedChild->MountToParent(columnNode);
219         child = columnNode;
220     } else {
221         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
222             AceType::MakeRefPtr<LinearLayoutPattern>(true));
223         auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
224         columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
225         columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
226         auto textNode = CreateMessage(message, useCustom);
227         bubblePattern->SetMessageNode(textNode);
228         auto popupTheme = GetPopupTheme();
229         auto padding = popupTheme->GetPadding();
230         auto layoutProps = textNode->GetLayoutProperty<TextLayoutProperty>();
231         PaddingProperty textPadding;
232         textPadding.left = CalcLength(padding.Left());
233         textPadding.right = CalcLength(padding.Right());
234         textPadding.top = CalcLength(padding.Top());
235         textPadding.bottom = CalcLength(padding.Bottom());
236         layoutProps->UpdatePadding(textPadding);
237         layoutProps->UpdateAlignment(Alignment::CENTER);
238         UpdateTextProperties(param, layoutProps);
239         auto buttonMiniMumHeight = popupTheme->GetBubbleMiniMumHeight().ConvertToPx();
240         layoutProps->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(buttonMiniMumHeight)));
241         textNode->MarkModifyDone();
242         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
243             textNode->MountToParent(columnNode);
244         } else {
245             auto scrollNode = FrameNode::CreateFrameNode(V2::SCROLL_ETS_TAG,
246                 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
247             CHECK_NULL_RETURN(scrollNode, nullptr);
248             auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
249             scrollProps->UpdateAxis(Axis::VERTICAL);
250             scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
251             scrollNode->MarkModifyDone();
252             textNode->MountToParent(scrollNode);
253             scrollNode->MountToParent(columnNode);
254         }
255         child = columnNode;
256     }
257     // GridSystemManager is not completed, need to check later.
258     auto childLayoutProperty = child->GetLayoutProperty();
259     CHECK_NULL_RETURN(childLayoutProperty, nullptr);
260     float popupMaxWidth = 0.0f;
261     float popupMaxHeight = 0.0f;
262     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
263     if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
264         childLayoutProperty->UpdateCalcMaxSize(
265             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
266     }
267     if (param->GetChildWidth().has_value()) {
268         childLayoutProperty->UpdateUserDefinedIdealSize(
269             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
270     }
271     auto renderContext = child->GetRenderContext();
272     if (renderContext) {
273         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
274             renderContext->UpdateBackgroundColor(
275                 popupPaintProp->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
276         } else {
277             auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(Color::TRANSPARENT);
278             renderContext->UpdateBackgroundColor(backgroundColor);
279             BlurStyleOption styleOption;
280             styleOption.blurStyle = param->GetBlurStyle();
281             renderContext->UpdateBackBlurStyle(styleOption);
282         }
283         if (param->GetShadow().has_value()) {
284             renderContext->UpdateBackShadow(param->GetShadow().value());
285         }
286     }
287     child->MountToParent(popupNode);
288     return popupNode;
289 }
CreateCustomBubbleNode(const std::string & targetTag,int32_t targetId,const RefPtr<UINode> & customNode,const RefPtr<PopupParam> & param)290 RefPtr<FrameNode> BubbleView::CreateCustomBubbleNode(
291     const std::string& targetTag, int32_t targetId, const RefPtr<UINode>& customNode, const RefPtr<PopupParam>& param)
292 {
293     auto popupId = ElementRegister::GetInstance()->MakeUniqueId();
294     auto popupNode =
295         FrameNode::CreateFrameNode(V2::POPUP_ETS_TAG, popupId, AceType::MakeRefPtr<BubblePattern>(targetId, targetTag));
296     auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
297     if (bubbleHub) {
298         bubbleHub->SetOnStateChange(param->GetOnStateChange());
299     }
300     auto popupPattern = popupNode->GetPattern<BubblePattern>();
301     popupPattern->SetCustomPopupTag(true);
302     // update bubble props
303     auto layoutProps = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
304     layoutProps->UpdateUseCustom(param->IsUseCustom());
305     layoutProps->UpdateEnableArrow(param->EnableArrow());
306     layoutProps->UpdatePlacement(param->GetPlacement());
307     layoutProps->UpdateShowInSubWindow(param->IsShowInSubWindow());
308     layoutProps->UpdateBlockEvent(param->IsBlockEvent());
309     if (param->GetArrowHeight().has_value()) {
310         layoutProps->UpdateArrowHeight(param->GetArrowHeight().value());
311     }
312     if (param->GetArrowWidth().has_value()) {
313         layoutProps->UpdateArrowWidth(param->GetArrowWidth().value());
314     }
315     if (param->GetRadius().has_value()) {
316         layoutProps->UpdateRadius(param->GetRadius().value());
317     }
318     layoutProps->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
319     SetHitTestMode(popupNode, param->IsBlockEvent());
320     auto displayWindowOffset = GetDisplayWindowRectOffset();
321     layoutProps->UpdateDisplayWindowOffset(displayWindowOffset);
322     layoutProps->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
323     if (param->GetTargetSpace().has_value()) {
324         layoutProps->UpdateTargetSpace(param->GetTargetSpace().value());
325     }
326     auto popupPaintProps = popupNode->GetPaintProperty<BubbleRenderProperty>();
327     popupPaintProps->UpdateUseCustom(param->IsUseCustom());
328     popupPaintProps->UpdateEnableArrow(param->EnableArrow());
329     if (param->GetArrowOffset().has_value()) {
330         popupPaintProps->UpdateArrowOffset(param->GetArrowOffset().value());
331     }
332     if (param->IsMaskColorSetted()) {
333         popupPaintProps->UpdateMaskColor(param->GetMaskColor());
334     }
335     if (param->IsBackgroundColorSetted()) {
336         popupPaintProps->UpdateBackgroundColor(param->GetBackgroundColor());
337     }
338     if (param->GetHasTransition()) {
339         popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
340     }
341     popupPattern->SetHasTransition(param->GetHasTransition());
342 
343     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
344         AceType::MakeRefPtr<LinearLayoutPattern>(false));
345     auto columnNodeClip = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
346         AceType::MakeRefPtr<LinearLayoutPattern>(false));
347     auto clipContext = columnNodeClip->GetRenderContext();
348     clipContext->SetClipToBounds(true);
349     customNode->MountToParent(columnNodeClip);
350     columnNodeClip->MountToParent(columnNode);
351     auto columnRenderContext = columnNode->GetRenderContext();
352     auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
353     CHECK_NULL_RETURN(columnLayoutProperty, nullptr);
354     columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
355     columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
356     auto customFrameNode = AceType::DynamicCast<FrameNode>(customNode);
357     float popupMaxWidth = 0.0f;
358     float popupMaxHeight = 0.0f;
359     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
360     columnLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
361     if (param->GetChildWidth().has_value()) {
362         columnLayoutProperty->UpdateUserDefinedIdealSize(
363             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
364     }
365     if (columnRenderContext) {
366         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
367             columnRenderContext->UpdateBackgroundColor(
368                 popupPaintProps->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
369         } else {
370             auto backgroundColor = popupPaintProps->GetBackgroundColor().value_or(Color::TRANSPARENT);
371             columnRenderContext->UpdateBackgroundColor(backgroundColor);
372             BlurStyleOption styleOption;
373             styleOption.blurStyle = param->GetBlurStyle();
374             columnRenderContext->UpdateBackBlurStyle(styleOption);
375         }
376         if (param->GetShadow().has_value()) {
377             columnRenderContext->UpdateBackShadow(param->GetShadow().value());
378         }
379     }
380     popupPaintProps->UpdateAutoCancel(!param->HasAction());
381     popupPaintProps->UpdatePlacement(param->GetPlacement());
382     columnNode->MountToParent(popupNode);
383     return popupNode;
384 }
385 
UpdateBubbleButtons(std::list<RefPtr<UINode>> & buttons,const RefPtr<PopupParam> & param)386 void BubbleView::UpdateBubbleButtons(std::list<RefPtr<UINode>>& buttons, const RefPtr<PopupParam>& param)
387 {
388     auto primaryButton = param->GetPrimaryButtonProperties();
389     auto secondaryButton = param->GetSecondaryButtonProperties();
390     if (primaryButton.showButton) {
391         auto button = AceType::DynamicCast<FrameNode>(buttons.front());
392         buttons.pop_front();
393         auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
394         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
395         layoutProperty->UpdateContent(primaryButton.value);
396         textNode->MarkModifyDone();
397         auto buttonEventHub = button->GetOrCreateGestureEventHub();
398         if (primaryButton.action) {
399             buttonEventHub->AddClickEvent(primaryButton.action);
400         }
401     }
402     if (secondaryButton.showButton) {
403         auto button = AceType::DynamicCast<FrameNode>(buttons.front());
404         buttons.pop_front();
405         auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
406         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
407         layoutProperty->UpdateContent(secondaryButton.value);
408         textNode->MarkModifyDone();
409         auto buttonEventHub = button->GetOrCreateGestureEventHub();
410         if (secondaryButton.action) {
411             buttonEventHub->AddClickEvent(secondaryButton.action);
412         }
413     }
414 }
415 
UpdateBubbleContent(int32_t popupId,const RefPtr<PopupParam> & param)416 void BubbleView::UpdateBubbleContent(int32_t popupId, const RefPtr<PopupParam>& param)
417 {
418     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
419     CHECK_NULL_VOID(popupNode);
420     auto message = param->GetMessage();
421     auto primaryButton = param->GetPrimaryButtonProperties();
422     auto secondaryButton = param->GetSecondaryButtonProperties();
423     auto columnNode = popupNode->GetFirstChild();
424     if (primaryButton.showButton || secondaryButton.showButton) {
425         CHECK_NULL_VOID(columnNode);
426         auto combinedChild = columnNode->GetFirstChild();
427         CHECK_NULL_VOID(combinedChild);
428         const auto& children = combinedChild->GetChildren();
429         for (const auto& child: children) {
430             if (child->GetTag() == V2::TEXT_ETS_TAG) {  // API10
431                 auto textNode = AceType::DynamicCast<FrameNode>(child);
432                 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
433                 layoutProperty->UpdateContent(message);
434                 UpdateTextProperties(param, layoutProperty);
435                 textNode->MarkModifyDone();
436             } else if (child->GetTag() == V2::SCROLL_ETS_TAG) {
437                 auto textNode = AceType::DynamicCast<FrameNode>(child->GetFirstChild());
438                 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
439                 layoutProperty->UpdateContent(message);
440                 UpdateTextProperties(param, layoutProperty);
441                 textNode->MarkModifyDone();
442             } else {
443                 auto buttons = child->GetChildren();
444                 UpdateBubbleButtons(buttons, param);
445             }
446         }
447     } else {
448         CHECK_NULL_VOID(columnNode);
449         auto childNode = columnNode->GetFirstChild();
450         if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
451             childNode = childNode->GetFirstChild();
452         }
453         auto textNode = AceType::DynamicCast<FrameNode>(childNode);
454         CHECK_NULL_VOID(textNode);
455         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
456         layoutProperty->UpdateContent(message);
457         UpdateTextProperties(param, layoutProperty);
458         textNode->MarkModifyDone();
459     }
460 }
461 
UpdatePopupParam(int32_t popupId,const RefPtr<PopupParam> & param,const RefPtr<FrameNode> & targetNode)462 void BubbleView::UpdatePopupParam(int32_t popupId, const RefPtr<PopupParam>& param, const RefPtr<FrameNode>& targetNode)
463 {
464     UpdateCommonParam(popupId, param, false);
465     UpdateBubbleContent(popupId, param);
466     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
467     CHECK_NULL_VOID(popupNode);
468     auto popupProp = AceType::DynamicCast<BubbleLayoutProperty>(popupNode->GetLayoutProperty());
469     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
470     auto message = param->GetMessage();
471     auto primaryButton = param->GetPrimaryButtonProperties();
472     auto secondaryButton = param->GetSecondaryButtonProperties();
473     if ((primaryButton.showButton || secondaryButton.showButton) &&
474         !(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
475         auto pipelineContext = PipelineBase::GetCurrentContext();
476         CHECK_NULL_VOID(pipelineContext);
477         float popupMaxWidth = 0.0f;
478         float popupMaxHeight = 0.0f;
479         GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
480         auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
481         CHECK_NULL_VOID(buttonTheme);
482         auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
483         CHECK_NULL_VOID(childNode);
484         const auto& children = childNode->GetChildren();
485         for (const auto& uinode : children) {
486             if (uinode->GetTag() == V2::SCROLL_ETS_TAG) {
487                 auto scrollNode = AceType::DynamicCast<FrameNode>(uinode);
488                 CHECK_NULL_VOID(scrollNode);
489                 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
490                 scrollProps->UpdateCalcMaxSize(CalcSize(
491                     std::nullopt, CalcLength(Dimension(popupMaxHeight) - buttonTheme->GetHeight() * DOUBLENESS)));
492             }
493         }
494     }
495     // Update layout props
496     popupProp->UpdateUseCustom(param->IsUseCustom());
497     popupProp->UpdateEnableArrow(param->EnableArrow());
498     popupProp->UpdatePlacement(param->GetPlacement());
499     auto displayWindowOffset = GetDisplayWindowRectOffset();
500     popupProp->UpdateDisplayWindowOffset(displayWindowOffset);
501     // Update paint props
502     popupPaintProp->UpdatePlacement(param->GetPlacement());
503     popupPaintProp->UpdateUseCustom(param->IsUseCustom());
504     popupPaintProp->UpdateEnableArrow(param->EnableArrow());
505 }
506 
UpdateCustomPopupParam(int32_t popupId,const RefPtr<PopupParam> & param)507 void BubbleView::UpdateCustomPopupParam(int32_t popupId, const RefPtr<PopupParam>& param)
508 {
509     UpdateCommonParam(popupId, param);
510     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
511     CHECK_NULL_VOID(popupNode);
512     auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
513     CHECK_NULL_VOID(popupLayoutProp);
514     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
515     CHECK_NULL_VOID(popupPaintProp);
516     popupLayoutProp->UpdatePlacement(param->GetPlacement());
517     popupPaintProp->UpdatePlacement(param->GetPlacement());
518     popupLayoutProp->UpdateEnableArrow(param->EnableArrow());
519     popupPaintProp->UpdateAutoCancel(!param->HasAction());
520     popupPaintProp->UpdateEnableArrow(param->EnableArrow());
521 }
522 
GetPopupMaxWidthAndHeight(const RefPtr<PopupParam> & param,float & popupMaxWidth,float & popupMaxHeight)523 void BubbleView::GetPopupMaxWidthAndHeight(const RefPtr<PopupParam>& param, float& popupMaxWidth, float& popupMaxHeight)
524 {
525     auto pipelineContext = PipelineContext::GetCurrentContext();
526     CHECK_NULL_VOID(pipelineContext);
527     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
528     auto safeAreaManager = pipelineContext->GetSafeAreaManager();
529     CHECK_NULL_VOID(safeAreaManager);
530     auto bottom = safeAreaManager->GetSystemSafeArea().bottom_.Length();
531     auto top = safeAreaManager->GetSystemSafeArea().top_.Length();
532     auto maxHeight = windowGlobalRect.Height();
533     if (param->IsShowInSubWindow()) {
534         maxHeight = SystemProperties::GetDeviceHeight();
535     }
536     popupMaxHeight = maxHeight - OUT_RANGE_SPACE.ConvertToPx() - OUT_RANGE_SPACE.ConvertToPx() - bottom - top;
537     popupMaxWidth = GetMaxWith().Value();
538 }
539 
UpdateCommonParam(int32_t popupId,const RefPtr<PopupParam> & param,bool custom)540 void BubbleView::UpdateCommonParam(int32_t popupId, const RefPtr<PopupParam>& param, bool custom)
541 {
542     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
543     CHECK_NULL_VOID(popupNode);
544     auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
545     if (bubbleHub) {
546         bubbleHub->SetOnStateChange(param->GetOnStateChange());
547     }
548     auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
549     CHECK_NULL_VOID(popupLayoutProp);
550     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
551     CHECK_NULL_VOID(popupPaintProp);
552     if (param->GetArrowOffset().has_value()) {
553         popupPaintProp->UpdateArrowOffset(param->GetArrowOffset().value());
554     }
555     popupLayoutProp->UpdateShowInSubWindow(param->IsShowInSubWindow());
556     popupLayoutProp->UpdateBlockEvent(param->IsBlockEvent());
557     popupLayoutProp->UpdateIsCaretMode(param->IsCaretMode());
558     if (param->GetErrorArrowHeight()) {
559         popupLayoutProp->ResetArrowHeight();
560     }
561     if (param->GetErrorArrowWidth()) {
562         popupLayoutProp->ResetArrowWidth();
563     }
564     if (param->GetErrorRadius()) {
565         popupLayoutProp->ResetRadius();
566     }
567     if (param->GetArrowHeight().has_value()) {
568         popupLayoutProp->UpdateArrowHeight(param->GetArrowHeight().value());
569     }
570     if (param->GetArrowWidth().has_value()) {
571         popupLayoutProp->UpdateArrowWidth(param->GetArrowWidth().value());
572     }
573     if (param->GetRadius().has_value()) {
574         popupLayoutProp->UpdateRadius(param->GetRadius().value());
575     }
576     popupLayoutProp->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
577     SetHitTestMode(popupNode, param->IsBlockEvent());
578     popupLayoutProp->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
579     if (param->IsMaskColorSetted()) {
580         popupPaintProp->UpdateMaskColor(param->GetMaskColor());
581     } else {
582         popupPaintProp->UpdateMaskColor(Color::TRANSPARENT);
583     }
584     if (param->GetTargetSpace().has_value()) {
585         popupLayoutProp->UpdateTargetSpace(param->GetTargetSpace().value());
586     }
587     if (param->IsBackgroundColorSetted()) {
588         popupPaintProp->UpdateBackgroundColor(param->GetBackgroundColor());
589     }
590     auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
591     CHECK_NULL_VOID(childNode);
592     auto renderContext = childNode->GetRenderContext();
593     if (renderContext && param->GetShadow().has_value()) {
594         renderContext->UpdateBackShadow(param->GetShadow().value());
595     }
596     auto childLayoutProperty = childNode->GetLayoutProperty();
597     CHECK_NULL_VOID(childLayoutProperty);
598     float popupMaxWidth = 0.0f;
599     float popupMaxHeight = 0.0f;
600     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
601     if (custom) {
602         childLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
603     } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
604         childLayoutProperty->UpdateCalcMaxSize(
605             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
606     }
607     if (param->GetChildWidth().has_value()) {
608         childLayoutProperty->UpdateUserDefinedIdealSize(
609             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
610     }
611     if (renderContext) {
612         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
613             renderContext->UpdateBackgroundColor(
614                 popupPaintProp->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
615         } else {
616             auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(Color::TRANSPARENT);
617             renderContext->UpdateBackgroundColor(backgroundColor);
618             BlurStyleOption styleOption;
619             styleOption.blurStyle = param->GetBlurStyle();
620             renderContext->UpdateBackBlurStyle(styleOption);
621         }
622     }
623     RefPtr<BubblePattern> bubblePattern = popupNode->GetPattern<BubblePattern>();
624     bubblePattern->SetHasTransition(param->GetHasTransition());
625     if (param->GetHasTransition()) {
626         popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
627     }
628 }
629 
CreateMessage(const std::string & message,bool IsUseCustom)630 RefPtr<FrameNode> BubbleView::CreateMessage(const std::string& message, bool IsUseCustom)
631 {
632     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
633     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
634     // The buttons in popupNode can not get focus, if the textNode in the button is not focusable
635     textNode->GetOrCreateFocusHub()->SetFocusable(true);
636     auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
637     layoutProperty->UpdateContent(message);
638     auto popupTheme = GetPopupTheme();
639     CHECK_NULL_RETURN(popupTheme, nullptr);
640     if (!IsUseCustom) {
641         layoutProperty->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
642         layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
643     } else {
644         layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
645     }
646     if (IsUseCustom) {
647         layoutProperty->UpdateTextColor(Color::BLACK);
648     } else {
649         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
650             layoutProperty->UpdateTextColor(popupTheme->GetFontColor());
651         } else {
652             layoutProperty->UpdateTextColor(popupTheme->GetFontPrimaryColor());
653         }
654     }
655     textNode->MarkModifyDone();
656     return textNode;
657 }
658 
CreateCombinedChild(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId,const RefPtr<FrameNode> & bobbleNode)659 RefPtr<FrameNode> BubbleView::CreateCombinedChild(
660     const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId, const RefPtr<FrameNode>& bobbleNode)
661 {
662     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
663         AceType::MakeRefPtr<LinearLayoutPattern>(true));
664     auto layoutProps = columnNode->GetLayoutProperty<LinearLayoutProperty>();
665     layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START); // mainAxisAlign
666     layoutProps->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
667     auto message = BubbleView::CreateMessage(param->GetMessage(), param->IsUseCustom());
668     auto bubblePattern = bobbleNode->GetPattern<BubblePattern>();
669     CHECK_NULL_RETURN(bubblePattern, nullptr);
670     bubblePattern->SetMessageNode(message);
671     auto popupTheme = GetPopupTheme();
672     CHECK_NULL_RETURN(popupTheme, nullptr);
673     auto padding = popupTheme->GetPadding();
674     auto textLayoutProps = message->GetLayoutProperty<TextLayoutProperty>();
675     PaddingProperty textPadding;
676     textPadding.left = CalcLength(padding.Left());
677     textPadding.right = CalcLength(padding.Right());
678     textPadding.top = CalcLength(padding.Top());
679     if (!param->IsUseCustom()) {
680         textPadding.left = CalcLength(popupTheme->GetAgingTextLeftPadding());
681         textPadding.right = CalcLength(popupTheme->GetAgingTextRightPadding());
682     }
683     textLayoutProps->UpdatePadding(textPadding);
684     textLayoutProps->UpdateAlignSelf(FlexAlign::FLEX_START);
685     UpdateTextProperties(param, textLayoutProps);
686     message->MarkModifyDone();
687     auto pipelineContext = PipelineBase::GetCurrentContext();
688     CHECK_NULL_RETURN(pipelineContext, nullptr);
689     float popupMaxWidth = 0.0f;
690     float popupMaxHeight = 0.0f;
691     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
692         message->MountToParent(columnNode);
693     } else {
694         GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
695         auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
696         CHECK_NULL_RETURN(buttonTheme, nullptr);
697         auto scrollNode = FrameNode::CreateFrameNode(
698             V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
699         CHECK_NULL_RETURN(scrollNode, nullptr);
700         auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
701         scrollProps->UpdateAxis(Axis::VERTICAL);
702         scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
703         auto buttonFontSize = popupTheme->GetButtonFontSize();
704         auto fontScale = pipelineContext->GetFontScale();
705         if (fontScale == AGE_SCALE_NUMBER) {
706             scrollProps->UpdateCalcMaxSize(CalcSize(
707                 std::nullopt, CalcLength(Dimension(popupMaxHeight) - GetAgeFontSize(buttonFontSize) *
708                 AGE_BUTTONS_LAYOUT_HEIGHT_RATE * DOUBLENESS)));
709         } else {
710             scrollProps->UpdateCalcMaxSize(
711                 CalcSize(std::nullopt, CalcLength(Dimension(popupMaxHeight) -
712                 GetAgeFontSize(buttonFontSize) * AGE_BUTTONS_LAYOUT_HEIGHT_RATE)));
713         }
714         scrollNode->MarkModifyDone();
715         message->MountToParent(scrollNode);
716         scrollNode->MountToParent(columnNode);
717     }
718     auto buttonLayout = BubbleView::CreateButtons(param, popupId, targetId);
719     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
720         auto buttonRowLayoutProperty = buttonLayout->GetLayoutProperty<LinearLayoutProperty>();
721         buttonRowLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
722     } else {
723         auto buttonFlexLayoutProperty = buttonLayout->GetLayoutProperty<FlexLayoutProperty>();
724         buttonFlexLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
725     }
726     buttonLayout->MarkModifyDone();
727     auto childLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
728     CHECK_NULL_RETURN(childLayoutProperty, nullptr);
729     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
730         popupMaxWidth = GetMaxWith().Value();
731         childLayoutProperty->UpdateCalcMaxSize(CalcSize(NG::CalcLength(popupMaxWidth), std::nullopt));
732     } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
733         childLayoutProperty->UpdateCalcMaxSize(
734             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
735     }
736     buttonLayout->MountToParent(columnNode);
737     columnNode->MarkModifyDone();
738     return columnNode;
739 }
740 
CreateButtons(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId)741 RefPtr<FrameNode> BubbleView::CreateButtons(const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId)
742 {
743     auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
744     RefPtr<FrameNode> layoutNode;
745     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
746         layoutNode =
747             FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
748     } else {
749         layoutNode = FrameNode::CreateFrameNode(V2::FLEX_ETS_TAG, rowId, AceType::MakeRefPtr<FlexLayoutPattern>(false));
750         layoutNode->GetPattern<FlexLayoutPattern>()->SetIsWrap(true);
751     }
752 
753     auto primaryButtonProp = param->GetPrimaryButtonProperties();
754     auto primaryButton = BubbleView::CreateButton(primaryButtonProp, popupId, targetId, param);
755     if (primaryButton) {
756         primaryButton->MountToParent(layoutNode);
757     }
758     auto secondaryButtonProp = param->GetSecondaryButtonProperties();
759     auto secondaryButton = BubbleView::CreateButton(secondaryButtonProp, popupId, targetId, param);
760     if (secondaryButton) {
761         secondaryButton->MountToParent(layoutNode);
762     }
763     auto popupTheme = GetPopupTheme();
764     CHECK_NULL_RETURN(popupTheme, nullptr);
765     auto littlePadding = popupTheme->GetLittlePadding();
766     PaddingProperty rowPadding;
767     rowPadding.right = CalcLength(littlePadding);
768     rowPadding.bottom = CalcLength(littlePadding);
769     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
770         auto layoutProps = layoutNode->GetLayoutProperty<LinearLayoutProperty>();
771         layoutProps->UpdateSpace(GetPopupTheme()->GetButtonSpacing());
772         layoutProps->UpdatePadding(rowPadding);
773     } else {
774         auto layoutProps = layoutNode->GetLayoutProperty<FlexLayoutProperty>();
775         layoutProps->UpdatePadding(rowPadding);
776     }
777     layoutNode->MarkModifyDone();
778     return layoutNode;
779 }
780 
UpdateButtonFontSize(RefPtr<TextLayoutProperty> & textLayoutProps)781 void UpdateButtonFontSize(RefPtr<TextLayoutProperty>& textLayoutProps)
782 {
783     auto popupTheme = GetPopupTheme();
784     CHECK_NULL_VOID(popupTheme);
785     auto pipeline = PipelineBase::GetCurrentContext();
786     auto fontSize = popupTheme->GetButtonFontSize();
787     auto fontSizeScale = pipeline->GetFontScale();
788     auto fontScale = fontSizeScale > AGE_FONT_MAX_SIZE_SCALE ? AGE_FONT_MAX_SIZE_SCALE : fontSizeScale;
789     if (fontScale == AGE_SCALE_NUMBER) {
790         textLayoutProps->UpdateAdaptMaxFontSize(popupTheme->GetButtonFontSize());
791         textLayoutProps->UpdateAdaptMinFontSize(MIN_BUTTON_FONT_SIZE);
792     } else {
793         textLayoutProps->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
794     }
795     textLayoutProps->UpdateFontSize(fontSize);
796 }
797 
CreateButton(ButtonProperties & buttonParam,int32_t popupId,int32_t targetId,const RefPtr<PopupParam> & param)798 RefPtr<FrameNode> BubbleView::CreateButton(
799     ButtonProperties& buttonParam, int32_t popupId, int32_t targetId, const RefPtr<PopupParam>& param)
800 {
801     if (!buttonParam.showButton) {
802         return nullptr;
803     }
804     auto pipelineContext = PipelineBase::GetCurrentContext();
805     CHECK_NULL_RETURN(pipelineContext, nullptr);
806     auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
807     CHECK_NULL_RETURN(buttonTheme, nullptr);
808     auto popupTheme = GetPopupTheme();
809     auto focusColor = popupTheme->GetFocusColor();
810     auto buttonId = ElementRegister::GetInstance()->MakeUniqueId();
811     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
812     CHECK_NULL_RETURN(buttonPattern, nullptr);
813     // set button focus color
814     buttonPattern->setComponentButtonType(ComponentButtonType::POPUP);
815     buttonPattern->SetFocusBorderColor(focusColor);
816     auto buttonNode = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, buttonId, buttonPattern);
817     CHECK_NULL_RETURN(buttonPattern, nullptr);
818 
819     auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
820     auto isUseCustom = param->IsUseCustom();
821 
822     auto buttonTextNode = BubbleView::CreateMessage(buttonParam.value, isUseCustom);
823     auto textLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
824     UpdateButtonFontSize(textLayoutProperty);
825     textLayoutProperty->UpdateMaxLines(BUTTON_MAX_LINE);
826     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
827     PaddingProperty buttonTextPadding;
828     buttonTextPadding.left = CalcLength(popupTheme->GetAgingButtonTextLeftPadding());
829     buttonTextPadding.right = CalcLength(popupTheme->GetAgingButtonTextRightPadding());
830     textLayoutProperty->UpdatePadding(buttonTextPadding);
831     if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
832         textLayoutProperty->UpdateTextColor(popupTheme->GetButtonFontColor());
833     }
834     auto buttonTextInsideMargin = popupTheme->GetButtonTextInsideMargin();
835     buttonTextNode->MountToParent(buttonNode);
836 
837     PaddingProperty buttonPadding;
838     auto padding = buttonTheme->GetPadding();
839     buttonPadding.left = CalcLength(buttonTextInsideMargin);
840     buttonPadding.right = CalcLength(buttonTextInsideMargin);
841     if (!param->IsUseCustom()) {
842         buttonPadding.left = CalcLength(popupTheme->GetAgingButtonLeftPadding());
843         buttonPadding.right = CalcLength(popupTheme->GetAgingButtonRightPadding());
844         buttonProp->UpdatePadding(buttonPadding);
845     } else {
846         buttonProp->UpdatePadding(buttonPadding);
847     }
848     buttonProp->UpdateType(ButtonType::CAPSULE);
849     auto fontScale = pipelineContext->GetFontScale();
850     if (fontScale == AGE_SCALE_NUMBER) {
851         buttonProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(buttonTheme->GetHeight())));
852     }
853     buttonProp->UpdateAlignment(Alignment::CENTER);
854     auto buttonMiniMumWidth = popupTheme->GetButtonMiniMumWidth().ConvertToPx();
855     buttonProp->UpdateCalcMinSize(CalcSize(CalcLength(buttonMiniMumWidth), std::nullopt));
856     auto renderContext = buttonNode->GetRenderContext();
857     if (renderContext) {
858         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
859     }
860 
861     auto buttonEventHub = buttonNode->GetOrCreateGestureEventHub();
862     CHECK_NULL_RETURN(buttonEventHub, nullptr);
863     buttonEventHub->AddClickEvent(buttonParam.action);
864     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
865     auto closeCallback = [popupNode, targetId](GestureEvent& /* info */) {
866         auto container = Container::Current();
867         CHECK_NULL_VOID(container);
868         auto pipelineContext = container->GetPipelineContext();
869         CHECK_NULL_VOID(pipelineContext);
870         auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
871         CHECK_NULL_VOID(context);
872         auto overlayManager = context->GetOverlayManager();
873         CHECK_NULL_VOID(overlayManager);
874         auto popupInfo = overlayManager->GetPopupInfo(targetId);
875         popupInfo.markNeedUpdate = true;
876         overlayManager->HidePopup(targetId, popupInfo);
877     };
878     if (buttonParam.action) {
879         buttonEventHub->AddClickEvent(buttonParam.action);
880     } else {
881         buttonEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
882     }
883 
884     return buttonNode;
885 }
886 } // namespace OHOS::Ace::NG
887