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