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_ng/pattern/bubble/bubble_pattern.h"
29 #include "core/components_ng/pattern/button/button_pattern.h"
30 #include "core/components_ng/pattern/flex/flex_layout_pattern.h"
31 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
32 #include "core/components_ng/pattern/text/text_pattern.h"
33
34 namespace OHOS::Ace::NG {
35 namespace {
36 constexpr double DOUBLENESS = 2.0;
37 constexpr Dimension OUT_RANGE_SPACE = 40.0_vp;
38 constexpr Dimension MAX_WIDTH = 400.0_vp;
39 constexpr Dimension MIN_BUTTON_FONT_SIZE = 9.0_vp;
40 constexpr int32_t TIPS_MAX_LINE = 1;
41 constexpr int32_t BUTTON_MAX_LINE = 2;
42 constexpr float AGE_FONT_MAX_SIZE_SCALE = 2.0f;
43 constexpr float AGE_SCALE_NUMBER = 1.0f;
44 constexpr float AGE_BUTTONS_LAYOUT_HEIGHT_RATE = 15.0f;
45
GetDisplayWindowRectOffset(int32_t popupNodeId)46 OffsetF GetDisplayWindowRectOffset(int32_t popupNodeId)
47 {
48 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupNodeId);
49 CHECK_NULL_RETURN(popupNode, OffsetF());
50 auto pipelineContext = popupNode->GetContextRefPtr();
51 CHECK_NULL_RETURN(pipelineContext, OffsetF());
52 auto overlayManager = pipelineContext->GetOverlayManager();
53 CHECK_NULL_RETURN(overlayManager, OffsetF());
54 auto displayWindowOffset = OffsetF(pipelineContext->GetDisplayWindowRectInfo().GetOffset().GetX(),
55 pipelineContext->GetDisplayWindowRectInfo().GetOffset().GetY());
56 return displayWindowOffset;
57 }
58
GetPopupTheme()59 RefPtr<PopupTheme> GetPopupTheme()
60 {
61 auto pipeline = PipelineBase::GetCurrentContext();
62 CHECK_NULL_RETURN(pipeline, nullptr);
63 auto popupTheme = pipeline->GetTheme<PopupTheme>();
64 CHECK_NULL_RETURN(popupTheme, nullptr);
65 return popupTheme;
66 }
67
GetMaxWith()68 Dimension GetMaxWith()
69 {
70 auto gridColumnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::BUBBLE_TYPE);
71 auto parent = gridColumnInfo->GetParent();
72 if (parent) {
73 parent->BuildColumnWidth();
74 }
75 auto maxWidth = Dimension(gridColumnInfo->GetMaxWidth());
76 auto popupTheme = GetPopupTheme();
77 CHECK_NULL_RETURN(popupTheme, maxWidth);
78 uint32_t maxColumns = popupTheme->GetMaxColumns();
79 if (maxColumns > 0) {
80 maxWidth = Dimension(gridColumnInfo->GetWidth(maxColumns));
81 }
82 return maxWidth;
83 }
84
GetAgeFontSize(const std::optional<Dimension> & originalFontSize)85 Dimension GetAgeFontSize(const std::optional<Dimension>& originalFontSize)
86 {
87 auto fontSize = Dimension(originalFontSize->Value(), originalFontSize->Unit());
88 auto pipeline = PipelineBase::GetCurrentContext();
89 CHECK_NULL_RETURN(pipeline, fontSize);
90 auto fontSizeScale = pipeline->GetFontScale();
91 auto fontScale = fontSizeScale > AGE_FONT_MAX_SIZE_SCALE ? AGE_FONT_MAX_SIZE_SCALE : fontSizeScale;
92 fontSize.SetValue((originalFontSize->Value()) * fontScale);
93 return fontSize;
94 }
95
UpdateTextProperties(const RefPtr<PopupParam> & param,const RefPtr<TextLayoutProperty> & textLayoutProps)96 void UpdateTextProperties(const RefPtr<PopupParam>& param, const RefPtr<TextLayoutProperty>& textLayoutProps)
97 {
98 auto textColor = param->GetTextColor();
99 if (textColor.has_value()) {
100 textLayoutProps->UpdateTextColor(textColor.value());
101 }
102 auto fontSize = param->GetFontSize();
103 if (fontSize.has_value()) {
104 if (!param->IsUseCustom()) {
105 textLayoutProps->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
106 textLayoutProps->UpdateFontSize(fontSize.value());
107 } else {
108 textLayoutProps->UpdateFontSize(fontSize.value());
109 }
110 }
111 auto fontWeight = param->GetFontWeight();
112 if (fontWeight.has_value()) {
113 textLayoutProps->UpdateFontWeight(fontWeight.value());
114 }
115 auto fontStyle = param->GetFontStyle();
116 if (fontStyle.has_value()) {
117 textLayoutProps->UpdateItalicFontStyle(fontStyle.value());
118 }
119 }
120 } // namespace
121
SetHitTestMode(RefPtr<FrameNode> & popupNode,bool isBlockEvent)122 void SetHitTestMode(RefPtr<FrameNode>& popupNode, bool isBlockEvent)
123 {
124 auto hub = popupNode->GetEventHub<BubbleEventHub>();
125 if (hub) {
126 auto ges = hub->GetOrCreateGestureEventHub();
127 CHECK_NULL_VOID(ges);
128 if (!isBlockEvent) {
129 ges->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
130 } else {
131 ges->SetHitTestMode(HitTestMode::HTMDEFAULT);
132 }
133 }
134 }
135
CreateBubbleNode(const std::string & targetTag,int32_t targetId,const RefPtr<PopupParam> & param)136 RefPtr<FrameNode> BubbleView::CreateBubbleNode(
137 const std::string& targetTag, int32_t targetId, const RefPtr<PopupParam>& param)
138 {
139 auto popupId = ElementRegister::GetInstance()->MakeUniqueId();
140 ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::POPUP_ETS_TAG, popupId);
141 auto popupNode =
142 FrameNode::CreateFrameNode(V2::POPUP_ETS_TAG, popupId, AceType::MakeRefPtr<BubblePattern>(targetId, targetTag));
143 auto popupProp = AceType::DynamicCast<BubbleLayoutProperty>(popupNode->GetLayoutProperty());
144 auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
145 auto useCustom = param->IsUseCustom();
146
147 // onstateChange.
148 auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
149 if (bubbleHub) {
150 bubbleHub->SetOnStateChange(param->GetOnStateChange());
151 }
152
153 auto message = param->GetMessage();
154 auto primaryButton = param->GetPrimaryButtonProperties();
155 auto secondaryButton = param->GetSecondaryButtonProperties();
156 // Update props
157 popupProp->UpdateIsTips(param->IsTips());
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 popupProp->UpdateEnableHoverMode(param->EnableHoverMode());
166
167 if (param->GetArrowHeight().has_value()) {
168 popupProp->UpdateArrowHeight(param->GetArrowHeight().value());
169 }
170 if (param->GetArrowWidth().has_value()) {
171 popupProp->UpdateArrowWidth(param->GetArrowWidth().value());
172 }
173 if (param->GetRadius().has_value()) {
174 popupProp->UpdateRadius(param->GetRadius().value());
175 }
176 popupProp->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
177 SetHitTestMode(popupNode, param->IsBlockEvent());
178 if (param->GetTargetSpace().has_value()) {
179 popupProp->UpdateTargetSpace(param->GetTargetSpace().value());
180 }
181 auto displayWindowOffset = GetDisplayWindowRectOffset(popupId);
182 popupProp->UpdateDisplayWindowOffset(displayWindowOffset);
183 popupPaintProp->UpdateEnableArrow(param->EnableArrow());
184 popupPaintProp->UpdateIsTips(param->IsTips());
185 if (param->GetArrowOffset().has_value()) {
186 popupPaintProp->UpdateArrowOffset(param->GetArrowOffset().value());
187 }
188 if (param->IsMaskColorSetted()) {
189 popupPaintProp->UpdateMaskColor(param->GetMaskColor());
190 }
191 if (param->IsBackgroundColorSetted()) {
192 popupPaintProp->UpdateBackgroundColor(param->GetBackgroundColor());
193 }
194 popupPaintProp->UpdateAutoCancel(!param->HasAction());
195 popupPaintProp->UpdatePlacement(param->GetPlacement());
196 if (param->GetHasTransition()) {
197 popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
198 }
199
200 auto bubbleAccessibilityProperty = popupNode->GetAccessibilityProperty<AccessibilityProperty>();
201 CHECK_NULL_RETURN(bubbleAccessibilityProperty, nullptr);
202 bubbleAccessibilityProperty->SetText(message);
203 auto bubblePattern = popupNode->GetPattern<BubblePattern>();
204 auto textColor = param->GetTextColor();
205 bubblePattern->SetMessageColor(textColor.has_value());
206 bubblePattern->SetHasTransition(param->GetHasTransition());
207 bubblePattern->SetEnableHoverMode(param->EnableHoverMode());
208 bubblePattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
209 auto popupTheme = GetPopupTheme();
210 CHECK_NULL_RETURN(popupTheme, nullptr);
211 // Create child
212 RefPtr<FrameNode> child;
213 if (primaryButton.showButton || secondaryButton.showButton) {
214 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
215 AceType::MakeRefPtr<LinearLayoutPattern>(true));
216 auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
217 columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
218 columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
219 auto combinedChild = CreateCombinedChild(param, popupId, targetId, popupNode);
220 popupPaintProp->UpdatePrimaryButtonShow(primaryButton.showButton);
221 popupPaintProp->UpdateSecondaryButtonShow(secondaryButton.showButton);
222 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
223 popupPaintProp->UpdateAutoCancel(false);
224 }
225 combinedChild->MountToParent(columnNode);
226 child = columnNode;
227 } else {
228 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
229 AceType::MakeRefPtr<LinearLayoutPattern>(true));
230 auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
231 columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
232 columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
233 auto textNode = CreateMessage(message, useCustom);
234 bubblePattern->SetMessageNode(textNode);
235 auto popupTheme = GetPopupTheme();
236 auto padding = popupTheme->GetPadding();
237 auto layoutProps = textNode->GetLayoutProperty<TextLayoutProperty>();
238 if (param->IsTips()) {
239 layoutProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
240 layoutProps->UpdateMaxLines(TIPS_MAX_LINE);
241 }
242 PaddingProperty textPadding;
243 textPadding.left = CalcLength(padding.Left());
244 textPadding.right = CalcLength(padding.Right());
245 textPadding.top = CalcLength(padding.Top());
246 textPadding.bottom = CalcLength(padding.Bottom());
247 layoutProps->UpdatePadding(textPadding);
248 layoutProps->UpdateAlignment(Alignment::CENTER);
249 UpdateTextProperties(param, layoutProps);
250 auto buttonMiniMumHeight = popupTheme->GetBubbleMiniMumHeight().ConvertToPx();
251 layoutProps->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(buttonMiniMumHeight)));
252 textNode->MarkModifyDone();
253 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
254 textNode->MountToParent(columnNode);
255 } else {
256 auto scrollNode = FrameNode::CreateFrameNode(V2::SCROLL_ETS_TAG,
257 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
258 CHECK_NULL_RETURN(scrollNode, nullptr);
259 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
260 scrollProps->UpdateAxis(Axis::VERTICAL);
261 scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
262 scrollNode->MarkModifyDone();
263 textNode->MountToParent(scrollNode);
264 scrollNode->MountToParent(columnNode);
265 }
266 child = columnNode;
267 }
268 // GridSystemManager is not completed, need to check later.
269 auto childLayoutProperty = child->GetLayoutProperty();
270 CHECK_NULL_RETURN(childLayoutProperty, nullptr);
271 float popupMaxWidth = 0.0f;
272 float popupMaxHeight = 0.0f;
273 GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight, popupId);
274 if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
275 childLayoutProperty->UpdateCalcMaxSize(
276 CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
277 }
278 if (param->GetChildWidth().has_value()) {
279 childLayoutProperty->UpdateUserDefinedIdealSize(
280 CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
281 }
282 auto renderContext = child->GetRenderContext();
283 if (renderContext) {
284 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
285 IsSupportBlurStyle(renderContext, param->IsShowInSubWindow())) {
286 auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(popupTheme->GetDefaultBGColor());
287 renderContext->UpdateBackgroundColor(backgroundColor);
288 BlurStyleOption styleOption;
289 if (param->IsTips() && param->EnableArrow()) {
290 styleOption.blurStyle = static_cast<BlurStyle>(static_cast<int>(BlurStyle::BACKGROUND_REGULAR));
291 } else if (param->IsTips() && !(param->EnableArrow())) {
292 styleOption.blurStyle = static_cast<BlurStyle>(static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK));
293 } else {
294 styleOption.blurStyle = param->GetBlurStyle();
295 }
296 styleOption.blurStyle = param->GetBlurStyle();
297 styleOption.colorMode = static_cast<ThemeColorMode>(popupTheme->GetBgThemeColorMode());
298 renderContext->UpdateBackBlurStyle(styleOption);
299 } else {
300 renderContext->UpdateBackgroundColor(
301 popupPaintProp->GetBackgroundColor().value_or(popupTheme->GetBackgroundColor()));
302 }
303 if (param->GetShadow().has_value()) {
304 renderContext->UpdateBackShadow(param->GetShadow().value());
305 }
306 if (param->IsTips()) {
307 auto shadow = Shadow::CreateShadow(ShadowStyle::OuterDefaultSM);
308 renderContext->UpdateBackShadow(shadow);
309 }
310 }
311 child->MountToParent(popupNode);
312 return popupNode;
313 }
CreateCustomBubbleNode(const std::string & targetTag,int32_t targetId,const RefPtr<UINode> & customNode,const RefPtr<PopupParam> & param)314 RefPtr<FrameNode> BubbleView::CreateCustomBubbleNode(
315 const std::string& targetTag, int32_t targetId, const RefPtr<UINode>& customNode, const RefPtr<PopupParam>& param)
316 {
317 auto popupId = ElementRegister::GetInstance()->MakeUniqueId();
318 auto popupNode =
319 FrameNode::CreateFrameNode(V2::POPUP_ETS_TAG, popupId, AceType::MakeRefPtr<BubblePattern>(targetId, targetTag));
320 auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
321 if (bubbleHub) {
322 bubbleHub->SetOnStateChange(param->GetOnStateChange());
323 }
324 auto popupPattern = popupNode->GetPattern<BubblePattern>();
325 popupPattern->SetEnableHoverMode(param->EnableHoverMode());
326 popupPattern->SetCustomPopupTag(true);
327 // update bubble props
328 auto layoutProps = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
329 layoutProps->UpdateUseCustom(param->IsUseCustom());
330 layoutProps->UpdateEnableArrow(param->EnableArrow());
331 layoutProps->UpdatePlacement(param->GetPlacement());
332 layoutProps->UpdateShowInSubWindow(param->IsShowInSubWindow());
333 layoutProps->UpdateBlockEvent(param->IsBlockEvent());
334 if (param->GetArrowHeight().has_value()) {
335 layoutProps->UpdateArrowHeight(param->GetArrowHeight().value());
336 }
337 if (param->GetArrowWidth().has_value()) {
338 layoutProps->UpdateArrowWidth(param->GetArrowWidth().value());
339 }
340 if (param->GetRadius().has_value()) {
341 layoutProps->UpdateRadius(param->GetRadius().value());
342 }
343 layoutProps->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
344 SetHitTestMode(popupNode, param->IsBlockEvent());
345 auto displayWindowOffset = GetDisplayWindowRectOffset(popupId);
346 layoutProps->UpdateDisplayWindowOffset(displayWindowOffset);
347 layoutProps->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
348 if (param->GetTargetSpace().has_value()) {
349 layoutProps->UpdateTargetSpace(param->GetTargetSpace().value());
350 }
351 auto popupPaintProps = popupNode->GetPaintProperty<BubbleRenderProperty>();
352 popupPaintProps->UpdateUseCustom(param->IsUseCustom());
353 popupPaintProps->UpdateEnableArrow(param->EnableArrow());
354 if (param->GetArrowOffset().has_value()) {
355 popupPaintProps->UpdateArrowOffset(param->GetArrowOffset().value());
356 }
357 if (param->IsMaskColorSetted()) {
358 popupPaintProps->UpdateMaskColor(param->GetMaskColor());
359 }
360 if (param->IsBackgroundColorSetted()) {
361 popupPaintProps->UpdateBackgroundColor(param->GetBackgroundColor());
362 }
363 if (param->GetHasTransition()) {
364 popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
365 }
366 popupPattern->SetHasTransition(param->GetHasTransition());
367 popupPattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
368
369 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
370 AceType::MakeRefPtr<LinearLayoutPattern>(false));
371 auto columnNodeClip = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
372 AceType::MakeRefPtr<LinearLayoutPattern>(false));
373 auto clipContext = columnNodeClip->GetRenderContext();
374 clipContext->SetClipToBounds(true);
375 customNode->MountToParent(columnNodeClip);
376 columnNodeClip->MountToParent(columnNode);
377 auto columnRenderContext = columnNode->GetRenderContext();
378 auto columnLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
379 CHECK_NULL_RETURN(columnLayoutProperty, nullptr);
380 columnLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER); // mainAxisAlign
381 columnLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
382 auto customFrameNode = AceType::DynamicCast<FrameNode>(customNode);
383 float popupMaxWidth = 0.0f;
384 float popupMaxHeight = 0.0f;
385 GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight, popupId);
386 columnLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
387 if (param->GetChildWidth().has_value()) {
388 columnLayoutProperty->UpdateUserDefinedIdealSize(
389 CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
390 }
391 if (columnRenderContext) {
392 auto popupTheme = GetPopupTheme();
393 CHECK_NULL_RETURN(popupTheme, nullptr);
394 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
395 IsSupportBlurStyle(columnRenderContext, param->IsShowInSubWindow())) {
396 auto backgroundColor = popupPaintProps->GetBackgroundColor().value_or(popupTheme->GetDefaultBGColor());
397 columnRenderContext->UpdateBackgroundColor(backgroundColor);
398 BlurStyleOption styleOption;
399 styleOption.blurStyle = param->GetBlurStyle();
400 styleOption.colorMode = static_cast<ThemeColorMode>(popupTheme->GetBgThemeColorMode());
401 columnRenderContext->UpdateBackBlurStyle(styleOption);
402 } else {
403 columnRenderContext->UpdateBackgroundColor(
404 popupPaintProps->GetBackgroundColor().value_or(popupTheme->GetBackgroundColor()));
405 }
406 if (param->GetShadow().has_value()) {
407 columnRenderContext->UpdateBackShadow(param->GetShadow().value());
408 }
409 }
410 popupPaintProps->UpdateAutoCancel(!param->HasAction());
411 popupPaintProps->UpdatePlacement(param->GetPlacement());
412 columnNode->MountToParent(popupNode);
413 return popupNode;
414 }
415
UpdateBubbleButtons(std::list<RefPtr<UINode>> & buttons,const RefPtr<PopupParam> & param)416 void BubbleView::UpdateBubbleButtons(std::list<RefPtr<UINode>>& buttons, const RefPtr<PopupParam>& param)
417 {
418 auto primaryButton = param->GetPrimaryButtonProperties();
419 auto secondaryButton = param->GetSecondaryButtonProperties();
420 if (primaryButton.showButton) {
421 auto button = AceType::DynamicCast<FrameNode>(buttons.front());
422 buttons.pop_front();
423 auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
424 CHECK_NULL_VOID(textNode);
425 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
426 CHECK_NULL_VOID(layoutProperty);
427 layoutProperty->UpdateContent(primaryButton.value);
428 textNode->MarkModifyDone();
429 auto buttonEventHub = button->GetOrCreateGestureEventHub();
430 if (primaryButton.action) {
431 buttonEventHub->AddClickEvent(primaryButton.action);
432 }
433 }
434 if (secondaryButton.showButton) {
435 auto button = AceType::DynamicCast<FrameNode>(buttons.front());
436 buttons.pop_front();
437 auto textNode = AceType::DynamicCast<FrameNode>(button->GetFirstChild());
438 CHECK_NULL_VOID(textNode);
439 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
440 CHECK_NULL_VOID(layoutProperty);
441 layoutProperty->UpdateContent(secondaryButton.value);
442 textNode->MarkModifyDone();
443 auto buttonEventHub = button->GetOrCreateGestureEventHub();
444 if (secondaryButton.action) {
445 buttonEventHub->AddClickEvent(secondaryButton.action);
446 }
447 }
448 }
449
UpdateBubbleContent(int32_t popupId,const RefPtr<PopupParam> & param)450 void BubbleView::UpdateBubbleContent(int32_t popupId, const RefPtr<PopupParam>& param)
451 {
452 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
453 CHECK_NULL_VOID(popupNode);
454 auto message = param->GetMessage();
455 auto primaryButton = param->GetPrimaryButtonProperties();
456 auto secondaryButton = param->GetSecondaryButtonProperties();
457 auto columnNode = popupNode->GetFirstChild();
458 if (primaryButton.showButton || secondaryButton.showButton) {
459 CHECK_NULL_VOID(columnNode);
460 auto combinedChild = columnNode->GetFirstChild();
461 CHECK_NULL_VOID(combinedChild);
462 const auto& children = combinedChild->GetChildren();
463 for (const auto& child : children) {
464 if (child->GetTag() == V2::TEXT_ETS_TAG) { // API10
465 auto textNode = AceType::DynamicCast<FrameNode>(child);
466 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
467 CHECK_NULL_VOID(layoutProperty);
468 layoutProperty->UpdateContent(message);
469 UpdateTextProperties(param, layoutProperty);
470 textNode->MarkModifyDone();
471 } else if (child->GetTag() == V2::SCROLL_ETS_TAG) {
472 auto textNode = AceType::DynamicCast<FrameNode>(child->GetFirstChild());
473 CHECK_NULL_VOID(textNode);
474 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
475 CHECK_NULL_VOID(layoutProperty);
476 layoutProperty->UpdateContent(message);
477 UpdateTextProperties(param, layoutProperty);
478 textNode->MarkModifyDone();
479 } else {
480 auto buttons = child->GetChildren();
481 UpdateBubbleButtons(buttons, param);
482 }
483 }
484 } else {
485 CHECK_NULL_VOID(columnNode);
486 auto childNode = columnNode->GetFirstChild();
487 if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
488 childNode = childNode->GetFirstChild();
489 }
490 auto textNode = AceType::DynamicCast<FrameNode>(childNode);
491 CHECK_NULL_VOID(textNode);
492 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
493 CHECK_NULL_VOID(layoutProperty);
494 layoutProperty->UpdateContent(message);
495 UpdateTextProperties(param, layoutProperty);
496 textNode->MarkModifyDone();
497 }
498 }
499
UpdatePopupParam(int32_t popupId,const RefPtr<PopupParam> & param,const RefPtr<FrameNode> & targetNode)500 void BubbleView::UpdatePopupParam(int32_t popupId, const RefPtr<PopupParam>& param, const RefPtr<FrameNode>& targetNode)
501 {
502 UpdateCommonParam(popupId, param, false);
503 UpdateBubbleContent(popupId, param);
504 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
505 CHECK_NULL_VOID(popupNode);
506 auto popupProp = AceType::DynamicCast<BubbleLayoutProperty>(popupNode->GetLayoutProperty());
507 auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
508 auto message = param->GetMessage();
509 auto primaryButton = param->GetPrimaryButtonProperties();
510 auto secondaryButton = param->GetSecondaryButtonProperties();
511 if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
512 if (primaryButton.showButton || secondaryButton.showButton) {
513 auto pipelineContext = PipelineBase::GetCurrentContext();
514 CHECK_NULL_VOID(pipelineContext);
515 float popupMaxWidth = 0.0f;
516 float popupMaxHeight = 0.0f;
517 GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight, popupId);
518 auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
519 CHECK_NULL_VOID(buttonTheme);
520 auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
521 CHECK_NULL_VOID(childNode);
522 const auto& children = childNode->GetChildren();
523 for (const auto& uinode : children) {
524 if (uinode->GetTag() == V2::SCROLL_ETS_TAG) {
525 auto scrollNode = AceType::DynamicCast<FrameNode>(uinode);
526 CHECK_NULL_VOID(scrollNode);
527 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
528 scrollProps->UpdateCalcMaxSize(CalcSize(
529 std::nullopt, CalcLength(Dimension(popupMaxHeight) - buttonTheme->GetHeight() * DOUBLENESS)));
530 }
531 }
532 }
533 }
534 // Update layout props
535 popupProp->UpdateUseCustom(param->IsUseCustom());
536 popupProp->UpdateEnableArrow(param->EnableArrow());
537 popupProp->UpdatePlacement(param->GetPlacement());
538 auto displayWindowOffset = GetDisplayWindowRectOffset(popupId);
539 popupProp->UpdateDisplayWindowOffset(displayWindowOffset);
540 // Update paint props
541 popupPaintProp->UpdatePlacement(param->GetPlacement());
542 popupPaintProp->UpdateUseCustom(param->IsUseCustom());
543 popupPaintProp->UpdateEnableArrow(param->EnableArrow());
544 }
545
UpdateCustomPopupParam(int32_t popupId,const RefPtr<PopupParam> & param)546 void BubbleView::UpdateCustomPopupParam(int32_t popupId, const RefPtr<PopupParam>& param)
547 {
548 UpdateCommonParam(popupId, param);
549 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
550 CHECK_NULL_VOID(popupNode);
551 auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
552 CHECK_NULL_VOID(popupLayoutProp);
553 auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
554 CHECK_NULL_VOID(popupPaintProp);
555 popupLayoutProp->UpdatePlacement(param->GetPlacement());
556 popupPaintProp->UpdatePlacement(param->GetPlacement());
557 popupLayoutProp->UpdateEnableArrow(param->EnableArrow());
558 popupPaintProp->UpdateAutoCancel(!param->HasAction());
559 popupPaintProp->UpdateEnableArrow(param->EnableArrow());
560 }
561
GetPopupMaxWidthAndHeight(const RefPtr<PopupParam> & param,float & popupMaxWidth,float & popupMaxHeight,int32_t popupNodeId)562 void BubbleView::GetPopupMaxWidthAndHeight(
563 const RefPtr<PopupParam>& param, float& popupMaxWidth, float& popupMaxHeight, int32_t popupNodeId)
564 {
565 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupNodeId);
566 CHECK_NULL_VOID(popupNode);
567 auto pipelineContext = popupNode->GetContextRefPtr();
568 CHECK_NULL_VOID(pipelineContext);
569 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
570 TAG_LOGI(AceLogTag::ACE_OVERLAY, "popup GetDisplayWindowRectInfo: %{public}s", windowGlobalRect.ToString().c_str());
571 auto safeAreaManager = pipelineContext->GetSafeAreaManager();
572 CHECK_NULL_VOID(safeAreaManager);
573 auto bottom = safeAreaManager->GetSystemSafeArea().bottom_.Length();
574 auto top = safeAreaManager->GetSystemSafeArea().top_.Length();
575 auto maxHeight = windowGlobalRect.Height();
576 auto theme = pipelineContext->GetTheme<PopupTheme>();
577 CHECK_NULL_VOID(theme);
578 auto container = Container::Current();
579 CHECK_NULL_VOID(container);
580 auto isFreeMultiWindow = container->IsFreeMultiWindow();
581 bool isExpandDisplay;
582 if (param->IsTips()) {
583 isExpandDisplay = theme->GetTipsDoubleBorderEnable() || isFreeMultiWindow;
584 } else {
585 isExpandDisplay = theme->GetPopupDoubleBorderEnable() || isFreeMultiWindow;
586 }
587 if (param->IsShowInSubWindow()) {
588 if (isExpandDisplay) {
589 maxHeight = SystemProperties::GetDeviceHeight();
590 } else if (container->IsUIExtensionWindow()) {
591 auto focusWindowId = pipelineContext->GetFocusWindowId();
592 auto rect = container->GetUIExtensionHostWindowRect(focusWindowId);
593 TAG_LOGI(AceLogTag::ACE_OVERLAY, "popup GetUIExtensionHostWindowRect: %{public}s",
594 rect.ToString().c_str());
595 maxHeight = rect.Height();
596 }
597 }
598 popupMaxHeight = maxHeight - OUT_RANGE_SPACE.ConvertToPx() - OUT_RANGE_SPACE.ConvertToPx() - bottom - top;
599 popupMaxWidth = GetMaxWith().Value();
600 if (param->IsTips()) {
601 popupMaxWidth = (popupMaxWidth > MAX_WIDTH.ConvertToPx()) ? MAX_WIDTH.ConvertToPx() : popupMaxWidth;
602 }
603 }
604
UpdateCommonParam(int32_t popupId,const RefPtr<PopupParam> & param,bool custom)605 void BubbleView::UpdateCommonParam(int32_t popupId, const RefPtr<PopupParam>& param, bool custom)
606 {
607 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
608 CHECK_NULL_VOID(popupNode);
609 auto bubbleHub = popupNode->GetEventHub<BubbleEventHub>();
610 if (bubbleHub && (!(param->GetIsPartialUpdate().has_value()))) {
611 bubbleHub->SetOnStateChange(param->GetOnStateChange());
612 }
613 auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
614 CHECK_NULL_VOID(popupLayoutProp);
615 auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
616 CHECK_NULL_VOID(popupPaintProp);
617 if (param->GetArrowOffset().has_value()) {
618 popupPaintProp->UpdateArrowOffset(param->GetArrowOffset().value());
619 }
620 popupLayoutProp->UpdateShowInSubWindow(param->IsShowInSubWindow());
621 popupLayoutProp->UpdateBlockEvent(param->IsBlockEvent());
622 popupLayoutProp->UpdateIsCaretMode(param->IsCaretMode());
623 if (param->GetErrorArrowHeight()) {
624 popupLayoutProp->ResetArrowHeight();
625 }
626 if (param->GetErrorArrowWidth()) {
627 popupLayoutProp->ResetArrowWidth();
628 }
629 if (param->GetErrorRadius()) {
630 popupLayoutProp->ResetRadius();
631 }
632 if (param->GetArrowHeight().has_value()) {
633 popupLayoutProp->UpdateArrowHeight(param->GetArrowHeight().value());
634 }
635 if (param->GetArrowWidth().has_value()) {
636 popupLayoutProp->UpdateArrowWidth(param->GetArrowWidth().value());
637 }
638 if (param->GetRadius().has_value()) {
639 popupLayoutProp->UpdateRadius(param->GetRadius().value());
640 }
641 popupLayoutProp->UpdateFollowTransformOfTarget(param->IsFollowTransformOfTarget());
642 SetHitTestMode(popupNode, param->IsBlockEvent());
643 popupLayoutProp->UpdatePositionOffset(OffsetF(param->GetTargetOffset().GetX(), param->GetTargetOffset().GetY()));
644 if (param->IsMaskColorSetted()) {
645 popupPaintProp->UpdateMaskColor(param->GetMaskColor());
646 } else {
647 popupPaintProp->UpdateMaskColor(Color::TRANSPARENT);
648 }
649 if (param->GetTargetSpace().has_value()) {
650 popupLayoutProp->UpdateTargetSpace(param->GetTargetSpace().value());
651 }
652 if (param->IsBackgroundColorSetted()) {
653 popupPaintProp->UpdateBackgroundColor(param->GetBackgroundColor());
654 }
655 auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
656 CHECK_NULL_VOID(childNode);
657 auto renderContext = childNode->GetRenderContext();
658 if (renderContext && param->GetShadow().has_value()) {
659 renderContext->UpdateBackShadow(param->GetShadow().value());
660 }
661 auto childLayoutProperty = childNode->GetLayoutProperty();
662 CHECK_NULL_VOID(childLayoutProperty);
663 float popupMaxWidth = 0.0f;
664 float popupMaxHeight = 0.0f;
665 GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight, popupId);
666 if (custom) {
667 childLayoutProperty->UpdateCalcMaxSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(popupMaxHeight))));
668 } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
669 childLayoutProperty->UpdateCalcMaxSize(
670 CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
671 }
672 if (param->GetChildWidth().has_value()) {
673 childLayoutProperty->UpdateUserDefinedIdealSize(
674 CalcSize(CalcLength(param->GetChildWidth().value()), std::nullopt));
675 } else {
676 childLayoutProperty->ClearUserDefinedIdealSize(true, false);
677 }
678 if (renderContext) {
679 auto popupTheme = GetPopupTheme();
680 CHECK_NULL_VOID(popupTheme);
681 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
682 IsSupportBlurStyle(renderContext, param->IsShowInSubWindow())) {
683 auto defaultBGcolor = popupTheme->GetDefaultBGColor();
684 auto backgroundColor = popupPaintProp->GetBackgroundColor().value_or(defaultBGcolor);
685 renderContext->UpdateBackgroundColor(backgroundColor);
686 BlurStyleOption styleOption;
687 styleOption.blurStyle = param->GetBlurStyle();
688 styleOption.colorMode = static_cast<ThemeColorMode>(popupTheme->GetBgThemeColorMode());
689 renderContext->UpdateBackBlurStyle(styleOption);
690 } else {
691 renderContext->UpdateBackgroundColor(
692 popupPaintProp->GetBackgroundColor().value_or(popupTheme->GetBackgroundColor()));
693 }
694 }
695 RefPtr<BubblePattern> bubblePattern = popupNode->GetPattern<BubblePattern>();
696 bubblePattern->SetAvoidKeyboard(param->GetKeyBoardAvoidMode() == PopupKeyboardAvoidMode::DEFAULT);
697
698 if (!(param->GetIsPartialUpdate().has_value())) {
699 bubblePattern->SetHasTransition(param->GetHasTransition());
700 if (param->GetHasTransition()) {
701 popupNode->GetRenderContext()->UpdateChainedTransition(param->GetTransitionEffects());
702 }
703 }
704 }
705
ResetBubbleProperty(int32_t popupId)706 void BubbleView::ResetBubbleProperty(int32_t popupId)
707 {
708 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
709 CHECK_NULL_VOID(popupNode);
710 auto popupLayoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
711 CHECK_NULL_VOID(popupLayoutProp);
712 popupLayoutProp->ResetEnableArrow();
713 popupLayoutProp->ResetPlacement();
714 popupLayoutProp->ResetTargetSpace();
715 popupLayoutProp->ResetPositionOffset();
716 popupLayoutProp->ResetArrowHeight();
717 popupLayoutProp->ResetArrowWidth();
718 popupLayoutProp->ResetRadius();
719 popupLayoutProp->ResetFollowTransformOfTarget();
720
721 auto popupPaintProp = popupNode->GetPaintProperty<BubbleRenderProperty>();
722 CHECK_NULL_VOID(popupPaintProp);
723 popupPaintProp->ResetAutoCancel();
724 popupPaintProp->ResetBackgroundColor();
725 popupPaintProp->ResetEnableArrow();
726 popupPaintProp->ResetMaskColor();
727 popupPaintProp->ResetPlacement();
728 popupPaintProp->ResetArrowOffset();
729
730 auto childNode = AceType::DynamicCast<FrameNode>(popupNode->GetFirstChild());
731 CHECK_NULL_VOID(childNode);
732 auto renderContext = childNode->GetRenderContext();
733 if (renderContext) {
734 renderContext->ResetBackShadow();
735 }
736 auto childLayoutProperty = childNode->GetLayoutProperty();
737 CHECK_NULL_VOID(childLayoutProperty);
738 childLayoutProperty->ClearUserDefinedIdealSize(true, false);
739 }
740
CreateMessage(const std::string & message,bool IsUseCustom)741 RefPtr<FrameNode> BubbleView::CreateMessage(const std::string& message, bool IsUseCustom)
742 {
743 auto textId = ElementRegister::GetInstance()->MakeUniqueId();
744 auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
745 // The buttons in popupNode can not get focus, if the textNode in the button is not focusable
746 textNode->GetOrCreateFocusHub()->SetFocusable(true);
747 auto layoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
748 CHECK_NULL_RETURN(layoutProperty, nullptr);
749 layoutProperty->UpdateContent(message);
750 auto popupTheme = GetPopupTheme();
751 CHECK_NULL_RETURN(popupTheme, nullptr);
752 if (!IsUseCustom) {
753 layoutProperty->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
754 layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
755 } else {
756 layoutProperty->UpdateFontSize(popupTheme->GetFontSize());
757 }
758 if (IsUseCustom) {
759 layoutProperty->UpdateTextColor(Color::BLACK);
760 } else {
761 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
762 layoutProperty->UpdateTextColor(popupTheme->GetFontColor());
763 } else {
764 layoutProperty->UpdateTextColor(popupTheme->GetFontPrimaryColor());
765 }
766 }
767 textNode->MarkModifyDone();
768 return textNode;
769 }
770
CreateCombinedChild(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId,const RefPtr<FrameNode> & bobbleNode)771 RefPtr<FrameNode> BubbleView::CreateCombinedChild(
772 const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId, const RefPtr<FrameNode>& bobbleNode)
773 {
774 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
775 AceType::MakeRefPtr<LinearLayoutPattern>(true));
776 auto layoutProps = columnNode->GetLayoutProperty<LinearLayoutProperty>();
777 layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START); // mainAxisAlign
778 layoutProps->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
779 auto message = BubbleView::CreateMessage(param->GetMessage(), param->IsUseCustom());
780 auto bubblePattern = bobbleNode->GetPattern<BubblePattern>();
781 CHECK_NULL_RETURN(bubblePattern, nullptr);
782 bubblePattern->SetMessageNode(message);
783 auto popupTheme = GetPopupTheme();
784 CHECK_NULL_RETURN(popupTheme, nullptr);
785 auto padding = popupTheme->GetPadding();
786 auto textLayoutProps = message->GetLayoutProperty<TextLayoutProperty>();
787 PaddingProperty textPadding;
788 textPadding.left = CalcLength(padding.Left());
789 textPadding.right = CalcLength(padding.Right());
790 textPadding.top = CalcLength(padding.Top());
791 if (!param->IsUseCustom()) {
792 textPadding.left = CalcLength(popupTheme->GetAgingTextLeftPadding());
793 textPadding.right = CalcLength(popupTheme->GetAgingTextRightPadding());
794 }
795 textLayoutProps->UpdatePadding(textPadding);
796 textLayoutProps->UpdateAlignSelf(FlexAlign::FLEX_START);
797 UpdateTextProperties(param, textLayoutProps);
798 message->MarkModifyDone();
799 auto pipelineContext = PipelineBase::GetCurrentContext();
800 CHECK_NULL_RETURN(pipelineContext, nullptr);
801 float popupMaxWidth = 0.0f;
802 float popupMaxHeight = 0.0f;
803 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
804 message->MountToParent(columnNode);
805 } else {
806 GetPopupMaxWidthAndHeight(param, popupMaxWidth, popupMaxHeight, popupId);
807 auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
808 CHECK_NULL_RETURN(buttonTheme, nullptr);
809 auto scrollNode = FrameNode::CreateFrameNode(
810 V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
811 CHECK_NULL_RETURN(scrollNode, nullptr);
812 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
813 scrollProps->UpdateAxis(Axis::VERTICAL);
814 scrollProps->UpdateAlignment(Alignment::CENTER_LEFT);
815 auto buttonFontSize = popupTheme->GetButtonFontSize();
816 auto fontScale = pipelineContext->GetFontScale();
817 if (fontScale == AGE_SCALE_NUMBER) {
818 scrollProps->UpdateCalcMaxSize(CalcSize(
819 std::nullopt, CalcLength(Dimension(popupMaxHeight) - GetAgeFontSize(buttonFontSize) *
820 AGE_BUTTONS_LAYOUT_HEIGHT_RATE * DOUBLENESS)));
821 } else {
822 scrollProps->UpdateCalcMaxSize(
823 CalcSize(std::nullopt, CalcLength(Dimension(popupMaxHeight) -
824 GetAgeFontSize(buttonFontSize) * AGE_BUTTONS_LAYOUT_HEIGHT_RATE)));
825 }
826 scrollNode->MarkModifyDone();
827 message->MountToParent(scrollNode);
828 scrollNode->MountToParent(columnNode);
829 }
830 auto buttonLayout = BubbleView::CreateButtons(param, popupId, targetId);
831 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
832 auto buttonRowLayoutProperty = buttonLayout->GetLayoutProperty<LinearLayoutProperty>();
833 buttonRowLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
834 } else {
835 auto buttonFlexLayoutProperty = buttonLayout->GetLayoutProperty<FlexLayoutProperty>();
836 buttonFlexLayoutProperty->UpdateAlignSelf(FlexAlign::FLEX_END);
837 }
838 buttonLayout->MarkModifyDone();
839 auto childLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
840 CHECK_NULL_RETURN(childLayoutProperty, nullptr);
841 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
842 popupMaxWidth = GetMaxWith().Value();
843 childLayoutProperty->UpdateCalcMaxSize(CalcSize(NG::CalcLength(popupMaxWidth), std::nullopt));
844 } else if (GreatNotEqual(popupMaxWidth, 0.0f) && GreatNotEqual(popupMaxHeight, 0.0f)) {
845 childLayoutProperty->UpdateCalcMaxSize(
846 CalcSize(NG::CalcLength(Dimension(popupMaxWidth)), NG::CalcLength(Dimension(popupMaxHeight))));
847 }
848 buttonLayout->MountToParent(columnNode);
849 columnNode->MarkModifyDone();
850 return columnNode;
851 }
852
CreateButtons(const RefPtr<PopupParam> & param,int32_t popupId,int32_t targetId)853 RefPtr<FrameNode> BubbleView::CreateButtons(const RefPtr<PopupParam>& param, int32_t popupId, int32_t targetId)
854 {
855 auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
856 RefPtr<FrameNode> layoutNode;
857 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
858 layoutNode =
859 FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
860 } else {
861 layoutNode = FrameNode::CreateFrameNode(V2::FLEX_ETS_TAG, rowId, AceType::MakeRefPtr<FlexLayoutPattern>(false));
862 layoutNode->GetPattern<FlexLayoutPattern>()->SetIsWrap(true);
863 }
864
865 auto primaryButtonProp = param->GetPrimaryButtonProperties();
866 auto primaryButton = BubbleView::CreateButton(primaryButtonProp, popupId, targetId, param);
867 if (primaryButton) {
868 primaryButton->MountToParent(layoutNode);
869 }
870 auto secondaryButtonProp = param->GetSecondaryButtonProperties();
871 auto secondaryButton = BubbleView::CreateButton(secondaryButtonProp, popupId, targetId, param);
872 if (secondaryButton) {
873 secondaryButton->MountToParent(layoutNode);
874 }
875 auto popupTheme = GetPopupTheme();
876 CHECK_NULL_RETURN(popupTheme, nullptr);
877 auto littlePadding = popupTheme->GetLittlePadding();
878 PaddingProperty rowPadding;
879 rowPadding.right = CalcLength(littlePadding);
880 rowPadding.bottom = CalcLength(littlePadding);
881 if ((Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
882 auto layoutProps = layoutNode->GetLayoutProperty<LinearLayoutProperty>();
883 layoutProps->UpdateSpace(GetPopupTheme()->GetButtonSpacing());
884 layoutProps->UpdatePadding(rowPadding);
885 } else {
886 auto layoutProps = layoutNode->GetLayoutProperty<FlexLayoutProperty>();
887 layoutProps->UpdatePadding(rowPadding);
888 }
889 layoutNode->MarkModifyDone();
890 return layoutNode;
891 }
892
UpdateButtonFontSize(RefPtr<TextLayoutProperty> & textLayoutProps)893 void UpdateButtonFontSize(RefPtr<TextLayoutProperty>& textLayoutProps)
894 {
895 auto popupTheme = GetPopupTheme();
896 CHECK_NULL_VOID(popupTheme);
897 auto pipeline = PipelineBase::GetCurrentContext();
898 auto fontSize = popupTheme->GetButtonFontSize();
899 auto fontSizeScale = pipeline->GetFontScale();
900 auto fontScale = fontSizeScale > AGE_FONT_MAX_SIZE_SCALE ? AGE_FONT_MAX_SIZE_SCALE : fontSizeScale;
901 if (fontScale == AGE_SCALE_NUMBER) {
902 textLayoutProps->UpdateAdaptMaxFontSize(popupTheme->GetButtonFontSize());
903 textLayoutProps->UpdateAdaptMinFontSize(MIN_BUTTON_FONT_SIZE);
904 } else {
905 textLayoutProps->UpdateMaxFontScale(AGE_FONT_MAX_SIZE_SCALE);
906 }
907 textLayoutProps->UpdateFontSize(fontSize);
908 }
909
CreateButton(ButtonProperties & buttonParam,int32_t popupId,int32_t targetId,const RefPtr<PopupParam> & param)910 RefPtr<FrameNode> BubbleView::CreateButton(
911 ButtonProperties& buttonParam, int32_t popupId, int32_t targetId, const RefPtr<PopupParam>& param)
912 {
913 if (!buttonParam.showButton) {
914 return nullptr;
915 }
916 auto pipelineContext = PipelineBase::GetCurrentContext();
917 CHECK_NULL_RETURN(pipelineContext, nullptr);
918 auto buttonTheme = pipelineContext->GetTheme<ButtonTheme>();
919 CHECK_NULL_RETURN(buttonTheme, nullptr);
920 auto popupTheme = GetPopupTheme();
921 CHECK_NULL_RETURN(popupTheme, nullptr);
922 auto focusColor = popupTheme->GetFocusColor();
923 auto buttonId = ElementRegister::GetInstance()->MakeUniqueId();
924 auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
925 CHECK_NULL_RETURN(buttonPattern, nullptr);
926 // set button focus color
927 buttonPattern->setComponentButtonType(ComponentButtonType::POPUP);
928 buttonPattern->SetFocusBorderColor(focusColor);
929 auto buttonNode = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, buttonId, buttonPattern);
930 CHECK_NULL_RETURN(buttonPattern, nullptr);
931
932 auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
933 auto isUseCustom = param->IsUseCustom();
934
935 auto buttonTextNode = BubbleView::CreateMessage(buttonParam.value, isUseCustom);
936 auto textLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
937 UpdateButtonFontSize(textLayoutProperty);
938 textLayoutProperty->UpdateMaxLines(BUTTON_MAX_LINE);
939 textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
940 PaddingProperty buttonTextPadding;
941 buttonTextPadding.left = CalcLength(popupTheme->GetAgingButtonTextLeftPadding());
942 buttonTextPadding.right = CalcLength(popupTheme->GetAgingButtonTextRightPadding());
943 textLayoutProperty->UpdatePadding(buttonTextPadding);
944 if (!(Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
945 textLayoutProperty->UpdateTextColor(popupTheme->GetButtonFontColor());
946 }
947 auto buttonTextInsideMargin = popupTheme->GetButtonTextInsideMargin();
948 buttonTextNode->MountToParent(buttonNode);
949
950 PaddingProperty buttonPadding;
951 auto padding = buttonTheme->GetPadding();
952 buttonPadding.left = CalcLength(buttonTextInsideMargin);
953 buttonPadding.right = CalcLength(buttonTextInsideMargin);
954 if (!param->IsUseCustom()) {
955 buttonPadding.left = CalcLength(popupTheme->GetAgingButtonLeftPadding());
956 buttonPadding.right = CalcLength(popupTheme->GetAgingButtonRightPadding());
957 buttonProp->UpdatePadding(buttonPadding);
958 } else {
959 buttonProp->UpdatePadding(buttonPadding);
960 }
961 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
962 buttonProp->UpdateType(ButtonType::ROUNDED_RECTANGLE);
963 } else {
964 buttonProp->UpdateType(ButtonType::CAPSULE);
965 }
966 auto fontScale = pipelineContext->GetFontScale();
967 if (fontScale == AGE_SCALE_NUMBER) {
968 buttonProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(buttonTheme->GetHeight())));
969 }
970 buttonProp->UpdateAlignment(Alignment::CENTER);
971 auto buttonMiniMumWidth = popupTheme->GetButtonMiniMumWidth().ConvertToPx();
972 buttonProp->UpdateCalcMinSize(CalcSize(CalcLength(buttonMiniMumWidth), std::nullopt));
973 auto renderContext = buttonNode->GetRenderContext();
974 if (renderContext) {
975 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
976 }
977
978 auto buttonEventHub = buttonNode->GetOrCreateGestureEventHub();
979 CHECK_NULL_RETURN(buttonEventHub, nullptr);
980 buttonEventHub->AddClickEvent(buttonParam.action);
981 auto popupNode = FrameNode::GetFrameNode(V2::POPUP_ETS_TAG, popupId);
982 auto closeCallback = [popupNode, targetId](GestureEvent& /* info */) {
983 auto container = Container::Current();
984 CHECK_NULL_VOID(container);
985 auto pipelineContext = container->GetPipelineContext();
986 CHECK_NULL_VOID(pipelineContext);
987 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
988 CHECK_NULL_VOID(context);
989 auto overlayManager = context->GetOverlayManager();
990 CHECK_NULL_VOID(overlayManager);
991 auto popupInfo = overlayManager->GetPopupInfo(targetId);
992 popupInfo.markNeedUpdate = true;
993 overlayManager->HidePopup(targetId, popupInfo);
994 };
995 if (buttonParam.action) {
996 buttonEventHub->AddClickEvent(buttonParam.action);
997 } else {
998 buttonEventHub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
999 }
1000 buttonNode->MarkModifyDone();
1001 return buttonNode;
1002 }
1003
IsSupportBlurStyle(RefPtr<RenderContext> & renderContext,bool isShowInSubWindow)1004 bool BubbleView::IsSupportBlurStyle(RefPtr<RenderContext>& renderContext, bool isShowInSubWindow)
1005 {
1006 if (isShowInSubWindow) {
1007 return renderContext->IsUniRenderEnabled();
1008 }
1009 return true;
1010 }
1011
GetPopupInfoHelper(const RefPtr<UINode> & customNode,const std::function<PopupInfo (const RefPtr<OverlayManager> &)> & getPopupInfoFunc)1012 PopupInfo GetPopupInfoHelper(
1013 const RefPtr<UINode>& customNode, const std::function<PopupInfo(const RefPtr<OverlayManager>&)>& getPopupInfoFunc)
1014 {
1015 PopupInfo popupInfoError;
1016 auto context = customNode->GetContextWithCheck();
1017 CHECK_NULL_RETURN(context, popupInfoError);
1018 auto instanceId = context->GetInstanceId();
1019 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(instanceId, SubwindowType::TYPE_POPUP);
1020 if (subwindow) {
1021 auto overlayManager = subwindow->GetOverlayManager();
1022 if (overlayManager) {
1023 auto popupInfo = getPopupInfoFunc(overlayManager);
1024 if (popupInfo.popupNode) {
1025 return popupInfo;
1026 }
1027 }
1028 }
1029 auto overlayManager = context->GetOverlayManager();
1030 if (overlayManager) {
1031 auto popupInfo = getPopupInfoFunc(overlayManager);
1032 if (popupInfo.popupNode) {
1033 return popupInfo;
1034 }
1035 }
1036 return popupInfoError;
1037 }
1038
GetPopupInfoWithCustomNode(const RefPtr<UINode> & customNode)1039 PopupInfo BubbleView::GetPopupInfoWithCustomNode(const RefPtr<UINode>& customNode)
1040 {
1041 return GetPopupInfoHelper(customNode, [customNode](const RefPtr<OverlayManager>& overlayManager) {
1042 return overlayManager->GetPopupInfoWithExistContent(customNode);
1043 });
1044 }
1045
GetPopupInfoWithTargetId(const RefPtr<UINode> & customNode,const int32_t targetId)1046 PopupInfo BubbleView::GetPopupInfoWithTargetId(const RefPtr<UINode>& customNode, const int32_t targetId)
1047 {
1048 return GetPopupInfoHelper(customNode,
1049 [targetId](const RefPtr<OverlayManager>& overlayManager) { return overlayManager->GetPopupInfo(targetId); });
1050 }
1051
GetPopupOverlayManager(const RefPtr<UINode> & customNode,const int32_t targetId)1052 RefPtr<OverlayManager> BubbleView::GetPopupOverlayManager(const RefPtr<UINode>& customNode, const int32_t targetId)
1053 {
1054 auto context = customNode->GetContextWithCheck();
1055 CHECK_NULL_RETURN(context, nullptr);
1056 auto instanceId = context->GetInstanceId();
1057 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(instanceId, SubwindowType::TYPE_POPUP);
1058 if (subwindow) {
1059 auto overlayManager = subwindow->GetOverlayManager();
1060 if (overlayManager) {
1061 auto popupInfo = overlayManager->GetPopupInfo(targetId);
1062 if (popupInfo.popupNode) {
1063 return overlayManager;
1064 }
1065 }
1066 }
1067 auto overlayManager = context->GetOverlayManager();
1068 if (overlayManager) {
1069 auto popupInfo = overlayManager->GetPopupInfo(targetId);
1070 if (popupInfo.popupNode) {
1071 return overlayManager;
1072 }
1073 }
1074 return nullptr;
1075 }
1076 } // namespace OHOS::Ace::NG
1077