• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     bubblePattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
205     // Create child
206     RefPtr<FrameNode> child;
207     if (primaryButton.showButton || secondaryButton.showButton) {
208         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
209             AceType::MakeRefPtr<LinearLayoutPattern>(true));
210         auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
211         columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
212         columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
213         auto combinedChild = CreateCombinedChild(param, popupId, targetId, popupNode);
214         popupPaintProp->UpdatePrimaryButtonShow(primaryButton.showButton);
215         popupPaintProp->UpdateSecondaryButtonShow(secondaryButton.showButton);
216         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
217             popupPaintProp->UpdateAutoCancel(false);
218         }
219         combinedChild->MountToParent(columnNode);
220         child = columnNode;
221     } else {
222         auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
223             AceType::MakeRefPtr<LinearLayoutPattern>(true));
224         auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
225         columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
226         columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
227         auto textNode = CreateMessage(message, useCustom);
228         bubblePattern->SetMessageNode(textNode);
229         auto popupTheme = GetPopupTheme();
230         auto padding = popupTheme->GetPadding();
231         auto layoutProps = textNode->GetLayoutProperty<TextLayoutProperty>();
232         PaddingProperty textPadding;
233         textPadding.left = CalcLength(padding.Left());
234         textPadding.right = CalcLength(padding.Right());
235         textPadding.top = CalcLength(padding.Top());
236         textPadding.bottom = CalcLength(padding.Bottom());
237         layoutProps->UpdatePadding(textPadding);
238         layoutProps->UpdateAlignment(Alignment::CENTER);
239         UpdateTextProperties(param, layoutProps);
240         auto buttonMiniMumHeight = popupTheme->GetBubbleMiniMumHeight().ConvertToPx();
241         layoutProps->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(buttonMiniMumHeight)));
242         textNode->MarkModifyDone();
243         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
244             textNode->MountToParent(columnNode);
245         } else {
246             auto scrollNode = FrameNode::CreateFrameNode(V2::SCROLL_ETS_TAG,
247                 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
248             CHECK_NULL_RETURN(scrollNode, nullptr);
249             auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
250             scrollProps->UpdateAxis(Axis::VERTICAL);
251             scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
252             scrollNode->MarkModifyDone();
253             textNode->MountToParent(scrollNode);
254             scrollNode->MountToParent(columnNode);
255         }
256         child = columnNode;
257     }
258     // GridSystemManager is not completed, need to check later.
259     auto childLayoutProperty = child->GetLayoutProperty();
260     CHECK_NULL_RETURN(childLayoutProperty, nullptr);
261     float popupMaxWidth = 0.0f;
262     float popupMaxHeight = 0.0f;
263     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
264     if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
265         childLayoutProperty->UpdateCalcMaxSize(
266             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
267     }
268     if (param->GetChildWidth().has_value()) {
269         childLayoutProperty->UpdateUserDefinedIdealSize(
270             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
271     }
272     auto renderContext = child->GetRenderContext();
273     if (renderContext) {
274         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
275             renderContext->UpdateBackgroundColor(
276                 popupPaintProp->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
277         } else {
278             auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(Color::TRANSPARENT);
279             renderContext->UpdateBackgroundColor(backgroundColor);
280             BlurStyleOption styleOption;
281             styleOption.blurStyle = param->GetBlurStyle();
282             renderContext->UpdateBackBlurStyle(styleOption);
283         }
284         if (param->GetShadow().has_value()) {
285             renderContext->UpdateBackShadow(param->GetShadow().value());
286         }
287     }
288     child->MountToParent(popupNode);
289     return popupNode;
290 }
CreateCustomBubbleNode(const std::string & targetTag,int32_t targetId,const RefPtr<UINode> & customNode,const RefPtr<PopupParam> & param)291 RefPtr<FrameNode> BubbleView::CreateCustomBubbleNode(
292     const std::string& targetTag, int32_t targetId, const RefPtr<UINode>& customNode, const RefPtr<PopupParam>& param)
293 {
294     auto popupId = ElementRegister::GetInstance()->MakeUniqueId();
295     auto popupNode =
296         FrameNode::CreateFrameNode(V2::POPUP_ETS_TAG, popupId, AceType::MakeRefPtr<BubblePattern>(targetId, targetTag));
297     auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
298     if (bubbleHub) {
299         bubbleHub->SetOnStateChange(param->GetOnStateChange());
300     }
301     auto popupPattern = popupNode->GetPattern<BubblePattern>();
302     popupPattern->SetCustomPopupTag(true);
303     // update bubble props
304     auto layoutProps = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
305     layoutProps->UpdateUseCustom(param->IsUseCustom());
306     layoutProps->UpdateEnableArrow(param->EnableArrow());
307     layoutProps->UpdatePlacement(param->GetPlacement());
308     layoutProps->UpdateShowInSubWindow(param->IsShowInSubWindow());
309     layoutProps->UpdateBlockEvent(param->IsBlockEvent());
310     if (param->GetArrowHeight().has_value()) {
311         layoutProps->UpdateArrowHeight(param->GetArrowHeight().value());
312     }
313     if (param->GetArrowWidth().has_value()) {
314         layoutProps->UpdateArrowWidth(param->GetArrowWidth().value());
315     }
316     if (param->GetRadius().has_value()) {
317         layoutProps->UpdateRadius(param->GetRadius().value());
318     }
319     layoutProps->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
320     SetHitTestMode(popupNode, param->IsBlockEvent());
321     auto displayWindowOffset = GetDisplayWindowRectOffset();
322     layoutProps->UpdateDisplayWindowOffset(displayWindowOffset);
323     layoutProps->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
324     if (param->GetTargetSpace().has_value()) {
325         layoutProps->UpdateTargetSpace(param->GetTargetSpace().value());
326     }
327     auto popupPaintProps = popupNode->GetPaintProperty<BubbleRenderProperty>();
328     popupPaintProps->UpdateUseCustom(param->IsUseCustom());
329     popupPaintProps->UpdateEnableArrow(param->EnableArrow());
330     if (param->GetArrowOffset().has_value()) {
331         popupPaintProps->UpdateArrowOffset(param->GetArrowOffset().value());
332     }
333     if (param->IsMaskColorSetted()) {
334         popupPaintProps->UpdateMaskColor(param->GetMaskColor());
335     }
336     if (param->IsBackgroundColorSetted()) {
337         popupPaintProps->UpdateBackgroundColor(param->GetBackgroundColor());
338     }
339     if (param->GetHasTransition()) {
340         popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
341     }
342     popupPattern->SetHasTransition(param->GetHasTransition());
343     popupPattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
344 
345     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
346         AceType::MakeRefPtr<LinearLayoutPattern>(false));
347     auto columnNodeClip = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
348         AceType::MakeRefPtr<LinearLayoutPattern>(false));
349     auto clipContext = columnNodeClip->GetRenderContext();
350     clipContext->SetClipToBounds(true);
351     customNode->MountToParent(columnNodeClip);
352     columnNodeClip->MountToParent(columnNode);
353     auto columnRenderContext = columnNode->GetRenderContext();
354     auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
355     CHECK_NULL_RETURN(columnLayoutProperty, nullptr);
356     columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
357     columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
358     auto customFrameNode = AceType::DynamicCast<FrameNode>(customNode);
359     float popupMaxWidth = 0.0f;
360     float popupMaxHeight = 0.0f;
361     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
362     columnLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
363     if (param->GetChildWidth().has_value()) {
364         columnLayoutProperty->UpdateUserDefinedIdealSize(
365             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
366     }
367     if (columnRenderContext) {
368         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
369             columnRenderContext->UpdateBackgroundColor(
370                 popupPaintProps->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
371         } else {
372             auto backgroundColor = popupPaintProps->GetBackgroundColor().value_or(Color::TRANSPARENT);
373             columnRenderContext->UpdateBackgroundColor(backgroundColor);
374             BlurStyleOption styleOption;
375             styleOption.blurStyle = param->GetBlurStyle();
376             columnRenderContext->UpdateBackBlurStyle(styleOption);
377         }
378         if (param->GetShadow().has_value()) {
379             columnRenderContext->UpdateBackShadow(param->GetShadow().value());
380         }
381     }
382     popupPaintProps->UpdateAutoCancel(!param->HasAction());
383     popupPaintProps->UpdatePlacement(param->GetPlacement());
384     columnNode->MountToParent(popupNode);
385     return popupNode;
386 }
387 
UpdateBubbleButtons(std::list<RefPtr<UINode>> & buttons,const RefPtr<PopupParam> & param)388 void BubbleView::UpdateBubbleButtons(std::list<RefPtr<UINode>>& buttons, const RefPtr<PopupParam>& param)
389 {
390     auto primaryButton = param->GetPrimaryButtonProperties();
391     auto secondaryButton = param->GetSecondaryButtonProperties();
392     if (primaryButton.showButton) {
393         auto button = AceType::DynamicCast<FrameNode>(buttons.front());
394         buttons.pop_front();
395         auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
396         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
397         layoutProperty->UpdateContent(primaryButton.value);
398         textNode->MarkModifyDone();
399         auto buttonEventHub = button->GetOrCreateGestureEventHub();
400         if (primaryButton.action) {
401             buttonEventHub->AddClickEvent(primaryButton.action);
402         }
403     }
404     if (secondaryButton.showButton) {
405         auto button = AceType::DynamicCast<FrameNode>(buttons.front());
406         buttons.pop_front();
407         auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
408         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
409         layoutProperty->UpdateContent(secondaryButton.value);
410         textNode->MarkModifyDone();
411         auto buttonEventHub = button->GetOrCreateGestureEventHub();
412         if (secondaryButton.action) {
413             buttonEventHub->AddClickEvent(secondaryButton.action);
414         }
415     }
416 }
417 
UpdateBubbleContent(int32_t popupId,const RefPtr<PopupParam> & param)418 void BubbleView::UpdateBubbleContent(int32_t popupId, const RefPtr<PopupParam>& param)
419 {
420     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
421     CHECK_NULL_VOID(popupNode);
422     auto message = param->GetMessage();
423     auto primaryButton = param->GetPrimaryButtonProperties();
424     auto secondaryButton = param->GetSecondaryButtonProperties();
425     auto columnNode = popupNode->GetFirstChild();
426     if (primaryButton.showButton || secondaryButton.showButton) {
427         CHECK_NULL_VOID(columnNode);
428         auto combinedChild = columnNode->GetFirstChild();
429         CHECK_NULL_VOID(combinedChild);
430         const auto& children = combinedChild->GetChildren();
431         for (const auto& child: children) {
432             if (child->GetTag() == V2::TEXT_ETS_TAG) {  // API10
433                 auto textNode = AceType::DynamicCast<FrameNode>(child);
434                 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
435                 layoutProperty->UpdateContent(message);
436                 UpdateTextProperties(param, layoutProperty);
437                 textNode->MarkModifyDone();
438             } else if (child->GetTag() == V2::SCROLL_ETS_TAG) {
439                 auto textNode = AceType::DynamicCast<FrameNode>(child->GetFirstChild());
440                 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
441                 layoutProperty->UpdateContent(message);
442                 UpdateTextProperties(param, layoutProperty);
443                 textNode->MarkModifyDone();
444             } else {
445                 auto buttons = child->GetChildren();
446                 UpdateBubbleButtons(buttons, param);
447             }
448         }
449     } else {
450         CHECK_NULL_VOID(columnNode);
451         auto childNode = columnNode->GetFirstChild();
452         if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
453             childNode = childNode->GetFirstChild();
454         }
455         auto textNode = AceType::DynamicCast<FrameNode>(childNode);
456         CHECK_NULL_VOID(textNode);
457         auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
458         layoutProperty->UpdateContent(message);
459         UpdateTextProperties(param, layoutProperty);
460         textNode->MarkModifyDone();
461     }
462 }
463 
UpdatePopupParam(int32_t popupId,const RefPtr<PopupParam> & param,const RefPtr<FrameNode> & targetNode)464 void BubbleView::UpdatePopupParam(int32_t popupId, const RefPtr<PopupParam>& param, const RefPtr<FrameNode>& targetNode)
465 {
466     UpdateCommonParam(popupId, param, false);
467     UpdateBubbleContent(popupId, param);
468     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
469     CHECK_NULL_VOID(popupNode);
470     auto popupProp = AceType::DynamicCast<BubbleLayoutProperty>(popupNode->GetLayoutProperty());
471     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
472     auto message = param->GetMessage();
473     auto primaryButton = param->GetPrimaryButtonProperties();
474     auto secondaryButton = param->GetSecondaryButtonProperties();
475     if ((primaryButton.showButton || secondaryButton.showButton) &&
476         !(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
477         auto pipelineContext = PipelineBase::GetCurrentContext();
478         CHECK_NULL_VOID(pipelineContext);
479         float popupMaxWidth = 0.0f;
480         float popupMaxHeight = 0.0f;
481         GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
482         auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
483         CHECK_NULL_VOID(buttonTheme);
484         auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
485         CHECK_NULL_VOID(childNode);
486         const auto& children = childNode->GetChildren();
487         for (const auto& uinode : children) {
488             if (uinode->GetTag() == V2::SCROLL_ETS_TAG) {
489                 auto scrollNode = AceType::DynamicCast<FrameNode>(uinode);
490                 CHECK_NULL_VOID(scrollNode);
491                 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
492                 scrollProps->UpdateCalcMaxSize(CalcSize(
493                     std::nullopt, CalcLength(Dimension(popupMaxHeight) - buttonTheme->GetHeight() * DOUBLENESS)));
494             }
495         }
496     }
497     // Update layout props
498     popupProp->UpdateUseCustom(param->IsUseCustom());
499     popupProp->UpdateEnableArrow(param->EnableArrow());
500     popupProp->UpdatePlacement(param->GetPlacement());
501     auto displayWindowOffset = GetDisplayWindowRectOffset();
502     popupProp->UpdateDisplayWindowOffset(displayWindowOffset);
503     // Update paint props
504     popupPaintProp->UpdatePlacement(param->GetPlacement());
505     popupPaintProp->UpdateUseCustom(param->IsUseCustom());
506     popupPaintProp->UpdateEnableArrow(param->EnableArrow());
507 }
508 
UpdateCustomPopupParam(int32_t popupId,const RefPtr<PopupParam> & param)509 void BubbleView::UpdateCustomPopupParam(int32_t popupId, const RefPtr<PopupParam>& param)
510 {
511     UpdateCommonParam(popupId, param);
512     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
513     CHECK_NULL_VOID(popupNode);
514     auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
515     CHECK_NULL_VOID(popupLayoutProp);
516     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
517     CHECK_NULL_VOID(popupPaintProp);
518     popupLayoutProp->UpdatePlacement(param->GetPlacement());
519     popupPaintProp->UpdatePlacement(param->GetPlacement());
520     popupLayoutProp->UpdateEnableArrow(param->EnableArrow());
521     popupPaintProp->UpdateAutoCancel(!param->HasAction());
522     popupPaintProp->UpdateEnableArrow(param->EnableArrow());
523 }
524 
GetPopupMaxWidthAndHeight(const RefPtr<PopupParam> & param,float & popupMaxWidth,float & popupMaxHeight)525 void BubbleView::GetPopupMaxWidthAndHeight(const RefPtr<PopupParam>& param, float& popupMaxWidth, float& popupMaxHeight)
526 {
527     auto pipelineContext = PipelineContext::GetCurrentContext();
528     CHECK_NULL_VOID(pipelineContext);
529     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
530     auto safeAreaManager = pipelineContext->GetSafeAreaManager();
531     CHECK_NULL_VOID(safeAreaManager);
532     auto bottom = safeAreaManager->GetSystemSafeArea().bottom_.Length();
533     auto top = safeAreaManager->GetSystemSafeArea().top_.Length();
534     auto maxHeight = windowGlobalRect.Height();
535     if (param->IsShowInSubWindow()) {
536         maxHeight = SystemProperties::GetDeviceHeight();
537     }
538     popupMaxHeight = maxHeight - OUT_RANGE_SPACE.ConvertToPx() - OUT_RANGE_SPACE.ConvertToPx() - bottom - top;
539     popupMaxWidth = GetMaxWith().Value();
540 }
541 
UpdateCommonParam(int32_t popupId,const RefPtr<PopupParam> & param,bool custom)542 void BubbleView::UpdateCommonParam(int32_t popupId, const RefPtr<PopupParam>& param, bool custom)
543 {
544     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
545     CHECK_NULL_VOID(popupNode);
546     auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
547     if (bubbleHub) {
548         bubbleHub->SetOnStateChange(param->GetOnStateChange());
549     }
550     auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
551     CHECK_NULL_VOID(popupLayoutProp);
552     auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
553     CHECK_NULL_VOID(popupPaintProp);
554     if (param->GetArrowOffset().has_value()) {
555         popupPaintProp->UpdateArrowOffset(param->GetArrowOffset().value());
556     }
557     popupLayoutProp->UpdateShowInSubWindow(param->IsShowInSubWindow());
558     popupLayoutProp->UpdateBlockEvent(param->IsBlockEvent());
559     popupLayoutProp->UpdateIsCaretMode(param->IsCaretMode());
560     if (param->GetErrorArrowHeight()) {
561         popupLayoutProp->ResetArrowHeight();
562     }
563     if (param->GetErrorArrowWidth()) {
564         popupLayoutProp->ResetArrowWidth();
565     }
566     if (param->GetErrorRadius()) {
567         popupLayoutProp->ResetRadius();
568     }
569     if (param->GetArrowHeight().has_value()) {
570         popupLayoutProp->UpdateArrowHeight(param->GetArrowHeight().value());
571     }
572     if (param->GetArrowWidth().has_value()) {
573         popupLayoutProp->UpdateArrowWidth(param->GetArrowWidth().value());
574     }
575     if (param->GetRadius().has_value()) {
576         popupLayoutProp->UpdateRadius(param->GetRadius().value());
577     }
578     popupLayoutProp->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
579     SetHitTestMode(popupNode, param->IsBlockEvent());
580     popupLayoutProp->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
581     if (param->IsMaskColorSetted()) {
582         popupPaintProp->UpdateMaskColor(param->GetMaskColor());
583     } else {
584         popupPaintProp->UpdateMaskColor(Color::TRANSPARENT);
585     }
586     if (param->GetTargetSpace().has_value()) {
587         popupLayoutProp->UpdateTargetSpace(param->GetTargetSpace().value());
588     }
589     if (param->IsBackgroundColorSetted()) {
590         popupPaintProp->UpdateBackgroundColor(param->GetBackgroundColor());
591     }
592     auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
593     CHECK_NULL_VOID(childNode);
594     auto renderContext = childNode->GetRenderContext();
595     if (renderContext && param->GetShadow().has_value()) {
596         renderContext->UpdateBackShadow(param->GetShadow().value());
597     }
598     auto childLayoutProperty = childNode->GetLayoutProperty();
599     CHECK_NULL_VOID(childLayoutProperty);
600     float popupMaxWidth = 0.0f;
601     float popupMaxHeight = 0.0f;
602     GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
603     if (custom) {
604         childLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
605     } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
606         childLayoutProperty->UpdateCalcMaxSize(
607             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
608     }
609     if (param->GetChildWidth().has_value()) {
610         childLayoutProperty->UpdateUserDefinedIdealSize(
611             CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
612     }
613     if (renderContext) {
614         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
615             renderContext->UpdateBackgroundColor(
616                 popupPaintProp->GetBackgroundColor().value_or(GetPopupTheme()->GetBackgroundColor()));
617         } else {
618             auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(Color::TRANSPARENT);
619             renderContext->UpdateBackgroundColor(backgroundColor);
620             BlurStyleOption styleOption;
621             styleOption.blurStyle = param->GetBlurStyle();
622             renderContext->UpdateBackBlurStyle(styleOption);
623         }
624     }
625     RefPtr<BubblePattern> bubblePattern = popupNode->GetPattern<BubblePattern>();
626     bubblePattern->SetHasTransition(param->GetHasTransition());
627     bubblePattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
628     if (param->GetHasTransition()) {
629         popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
630     }
631 }
632 
CreateMessage(const std::string & message,bool IsUseCustom)633 RefPtr<FrameNode> BubbleView::CreateMessage(const std::string& message, bool IsUseCustom)
634 {
635     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
636     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
637     // The buttons in popupNode can not get focus, if the textNode in the button is not focusable
638     textNode->GetOrCreateFocusHub()->SetFocusable(true);
639     auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
640     layoutProperty->UpdateContent(message);
641     auto popupTheme = GetPopupTheme();
642     CHECK_NULL_RETURN(popupTheme, nullptr);
643     if (!IsUseCustom) {
644         layoutProperty->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
645         layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
646     } else {
647         layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
648     }
649     if (IsUseCustom) {
650         layoutProperty->UpdateTextColor(Color::BLACK);
651     } else {
652         if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
653             layoutProperty->UpdateTextColor(popupTheme->GetFontColor());
654         } else {
655             layoutProperty->UpdateTextColor(popupTheme->GetFontPrimaryColor());
656         }
657     }
658     textNode->MarkModifyDone();
659     return textNode;
660 }
661 
CreateCombinedChild(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId,const RefPtr<FrameNode> & bobbleNode)662 RefPtr<FrameNode> BubbleView::CreateCombinedChild(
663     const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId, const RefPtr<FrameNode>& bobbleNode)
664 {
665     auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
666         AceType::MakeRefPtr<LinearLayoutPattern>(true));
667     auto layoutProps = columnNode->GetLayoutProperty<LinearLayoutProperty>();
668     layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START); // mainAxisAlign
669     layoutProps->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
670     auto message = BubbleView::CreateMessage(param->GetMessage(), param->IsUseCustom());
671     auto bubblePattern = bobbleNode->GetPattern<BubblePattern>();
672     CHECK_NULL_RETURN(bubblePattern, nullptr);
673     bubblePattern->SetMessageNode(message);
674     auto popupTheme = GetPopupTheme();
675     CHECK_NULL_RETURN(popupTheme, nullptr);
676     auto padding = popupTheme->GetPadding();
677     auto textLayoutProps = message->GetLayoutProperty<TextLayoutProperty>();
678     PaddingProperty textPadding;
679     textPadding.left = CalcLength(padding.Left());
680     textPadding.right = CalcLength(padding.Right());
681     textPadding.top = CalcLength(padding.Top());
682     if (!param->IsUseCustom()) {
683         textPadding.left = CalcLength(popupTheme->GetAgingTextLeftPadding());
684         textPadding.right = CalcLength(popupTheme->GetAgingTextRightPadding());
685     }
686     textLayoutProps->UpdatePadding(textPadding);
687     textLayoutProps->UpdateAlignSelf(FlexAlign::FLEX_START);
688     UpdateTextProperties(param, textLayoutProps);
689     message->MarkModifyDone();
690     auto pipelineContext = PipelineBase::GetCurrentContext();
691     CHECK_NULL_RETURN(pipelineContext, nullptr);
692     float popupMaxWidth = 0.0f;
693     float popupMaxHeight = 0.0f;
694     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
695         message->MountToParent(columnNode);
696     } else {
697         GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight);
698         auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
699         CHECK_NULL_RETURN(buttonTheme, nullptr);
700         auto scrollNode = FrameNode::CreateFrameNode(
701             V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
702         CHECK_NULL_RETURN(scrollNode, nullptr);
703         auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
704         scrollProps->UpdateAxis(Axis::VERTICAL);
705         scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
706         auto buttonFontSize = popupTheme->GetButtonFontSize();
707         auto fontScale = pipelineContext->GetFontScale();
708         if (fontScale == AGE_SCALE_NUMBER) {
709             scrollProps->UpdateCalcMaxSize(CalcSize(
710                 std::nullopt, CalcLength(Dimension(popupMaxHeight) - GetAgeFontSize(buttonFontSize) *
711                 AGE_BUTTONS_LAYOUT_HEIGHT_RATE * DOUBLENESS)));
712         } else {
713             scrollProps->UpdateCalcMaxSize(
714                 CalcSize(std::nullopt, CalcLength(Dimension(popupMaxHeight) -
715                 GetAgeFontSize(buttonFontSize) * AGE_BUTTONS_LAYOUT_HEIGHT_RATE)));
716         }
717         scrollNode->MarkModifyDone();
718         message->MountToParent(scrollNode);
719         scrollNode->MountToParent(columnNode);
720     }
721     auto buttonLayout = BubbleView::CreateButtons(param, popupId, targetId);
722     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
723         auto buttonRowLayoutProperty = buttonLayout->GetLayoutProperty<LinearLayoutProperty>();
724         buttonRowLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
725     } else {
726         auto buttonFlexLayoutProperty = buttonLayout->GetLayoutProperty<FlexLayoutProperty>();
727         buttonFlexLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
728     }
729     buttonLayout->MarkModifyDone();
730     auto childLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
731     CHECK_NULL_RETURN(childLayoutProperty, nullptr);
732     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
733         popupMaxWidth = GetMaxWith().Value();
734         childLayoutProperty->UpdateCalcMaxSize(CalcSize(NG::CalcLength(popupMaxWidth), std::nullopt));
735     } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
736         childLayoutProperty->UpdateCalcMaxSize(
737             CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
738     }
739     buttonLayout->MountToParent(columnNode);
740     columnNode->MarkModifyDone();
741     return columnNode;
742 }
743 
CreateButtons(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId)744 RefPtr<FrameNode> BubbleView::CreateButtons(const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId)
745 {
746     auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
747     RefPtr<FrameNode> layoutNode;
748     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
749         layoutNode =
750             FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
751     } else {
752         layoutNode = FrameNode::CreateFrameNode(V2::FLEX_ETS_TAG, rowId, AceType::MakeRefPtr<FlexLayoutPattern>(false));
753         layoutNode->GetPattern<FlexLayoutPattern>()->SetIsWrap(true);
754     }
755 
756     auto primaryButtonProp = param->GetPrimaryButtonProperties();
757     auto primaryButton = BubbleView::CreateButton(primaryButtonProp, popupId, targetId, param);
758     if (primaryButton) {
759         primaryButton->MountToParent(layoutNode);
760     }
761     auto secondaryButtonProp = param->GetSecondaryButtonProperties();
762     auto secondaryButton = BubbleView::CreateButton(secondaryButtonProp, popupId, targetId, param);
763     if (secondaryButton) {
764         secondaryButton->MountToParent(layoutNode);
765     }
766     auto popupTheme = GetPopupTheme();
767     CHECK_NULL_RETURN(popupTheme, nullptr);
768     auto littlePadding = popupTheme->GetLittlePadding();
769     PaddingProperty rowPadding;
770     rowPadding.right = CalcLength(littlePadding);
771     rowPadding.bottom = CalcLength(littlePadding);
772     if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
773         auto layoutProps = layoutNode->GetLayoutProperty<LinearLayoutProperty>();
774         layoutProps->UpdateSpace(GetPopupTheme()->GetButtonSpacing());
775         layoutProps->UpdatePadding(rowPadding);
776     } else {
777         auto layoutProps = layoutNode->GetLayoutProperty<FlexLayoutProperty>();
778         layoutProps->UpdatePadding(rowPadding);
779     }
780     layoutNode->MarkModifyDone();
781     return layoutNode;
782 }
783 
UpdateButtonFontSize(RefPtr<TextLayoutProperty> & textLayoutProps)784 void UpdateButtonFontSize(RefPtr<TextLayoutProperty>& textLayoutProps)
785 {
786     auto popupTheme = GetPopupTheme();
787     CHECK_NULL_VOID(popupTheme);
788     auto pipeline = PipelineBase::GetCurrentContext();
789     auto fontSize = popupTheme->GetButtonFontSize();
790     auto fontSizeScale = pipeline->GetFontScale();
791     auto fontScale = fontSizeScale > AGE_FONT_MAX_SIZE_SCALE ? AGE_FONT_MAX_SIZE_SCALE : fontSizeScale;
792     if (fontScale == AGE_SCALE_NUMBER) {
793         textLayoutProps->UpdateAdaptMaxFontSize(popupTheme->GetButtonFontSize());
794         textLayoutProps->UpdateAdaptMinFontSize(MIN_BUTTON_FONT_SIZE);
795     } else {
796         textLayoutProps->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
797     }
798     textLayoutProps->UpdateFontSize(fontSize);
799 }
800 
CreateButton(ButtonProperties & buttonParam,int32_t popupId,int32_t targetId,const RefPtr<PopupParam> & param)801 RefPtr<FrameNode> BubbleView::CreateButton(
802     ButtonProperties& buttonParam, int32_t popupId, int32_t targetId, const RefPtr<PopupParam>& param)
803 {
804     if (!buttonParam.showButton) {
805         return nullptr;
806     }
807     auto pipelineContext = PipelineBase::GetCurrentContext();
808     CHECK_NULL_RETURN(pipelineContext, nullptr);
809     auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
810     CHECK_NULL_RETURN(buttonTheme, nullptr);
811     auto popupTheme = GetPopupTheme();
812     auto focusColor = popupTheme->GetFocusColor();
813     auto buttonId = ElementRegister::GetInstance()->MakeUniqueId();
814     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
815     CHECK_NULL_RETURN(buttonPattern, nullptr);
816     // set button focus color
817     buttonPattern->setComponentButtonType(ComponentButtonType::POPUP);
818     buttonPattern->SetFocusBorderColor(focusColor);
819     auto buttonNode = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, buttonId, buttonPattern);
820     CHECK_NULL_RETURN(buttonPattern, nullptr);
821 
822     auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
823     auto isUseCustom = param->IsUseCustom();
824 
825     auto buttonTextNode = BubbleView::CreateMessage(buttonParam.value, isUseCustom);
826     auto textLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
827     UpdateButtonFontSize(textLayoutProperty);
828     textLayoutProperty->UpdateMaxLines(BUTTON_MAX_LINE);
829     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
830     PaddingProperty buttonTextPadding;
831     buttonTextPadding.left = CalcLength(popupTheme->GetAgingButtonTextLeftPadding());
832     buttonTextPadding.right = CalcLength(popupTheme->GetAgingButtonTextRightPadding());
833     textLayoutProperty->UpdatePadding(buttonTextPadding);
834     if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
835         textLayoutProperty->UpdateTextColor(popupTheme->GetButtonFontColor());
836     }
837     auto buttonTextInsideMargin = popupTheme->GetButtonTextInsideMargin();
838     buttonTextNode->MountToParent(buttonNode);
839 
840     PaddingProperty buttonPadding;
841     auto padding = buttonTheme->GetPadding();
842     buttonPadding.left = CalcLength(buttonTextInsideMargin);
843     buttonPadding.right = CalcLength(buttonTextInsideMargin);
844     if (!param->IsUseCustom()) {
845         buttonPadding.left = CalcLength(popupTheme->GetAgingButtonLeftPadding());
846         buttonPadding.right = CalcLength(popupTheme->GetAgingButtonRightPadding());
847         buttonProp->UpdatePadding(buttonPadding);
848     } else {
849         buttonProp->UpdatePadding(buttonPadding);
850     }
851     buttonProp->UpdateType(ButtonType::CAPSULE);
852     auto fontScale = pipelineContext->GetFontScale();
853     if (fontScale == AGE_SCALE_NUMBER) {
854         buttonProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(buttonTheme->GetHeight())));
855     }
856     buttonProp->UpdateAlignment(Alignment::CENTER);
857     auto buttonMiniMumWidth = popupTheme->GetButtonMiniMumWidth().ConvertToPx();
858     buttonProp->UpdateCalcMinSize(CalcSize(CalcLength(buttonMiniMumWidth), std::nullopt));
859     auto renderContext = buttonNode->GetRenderContext();
860     if (renderContext) {
861         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
862     }
863 
864     auto buttonEventHub = buttonNode->GetOrCreateGestureEventHub();
865     CHECK_NULL_RETURN(buttonEventHub, nullptr);
866     buttonEventHub->AddClickEvent(buttonParam.action);
867     auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
868     auto closeCallback = [popupNode, targetId](GestureEvent& /* info */) {
869         auto container = Container::Current();
870         CHECK_NULL_VOID(container);
871         auto pipelineContext = container->GetPipelineContext();
872         CHECK_NULL_VOID(pipelineContext);
873         auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
874         CHECK_NULL_VOID(context);
875         auto overlayManager = context->GetOverlayManager();
876         CHECK_NULL_VOID(overlayManager);
877         auto popupInfo = overlayManager->GetPopupInfo(targetId);
878         popupInfo.markNeedUpdate = true;
879         overlayManager->HidePopup(targetId, popupInfo);
880     };
881     if (buttonParam.action) {
882         buttonEventHub->AddClickEvent(buttonParam.action);
883     } else {
884         buttonEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
885     }
886 
887     return buttonNode;
888 }
889 } // namespace OHOS::Ace::NG
890