• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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/dialog/dialog_pattern.h"
16 
17 #include <climits>
18 #include <cstdint>
19 #include <cstring>
20 
21 #include "base/log/dump_log.h"
22 #include "base/log/log.h"
23 #include "base/memory/ace_type.h"
24 #include "base/memory/referenced.h"
25 #include "base/subwindow/subwindow_manager.h"
26 #include "base/utils/measure_util.h"
27 #include "base/utils/utf_helper.h"
28 #include "core/common/ace_engine.h"
29 #include "core/common/container.h"
30 #include "core/common/recorder/event_recorder.h"
31 #include "core/components/button/button_theme.h"
32 #include "core/components/common/properties/alignment.h"
33 #include "core/components/theme/icon_theme.h"
34 #include "core/components/theme/shadow_theme.h"
35 #include "core/components_ng/base/frame_node.h"
36 #include "core/components_ng/base/inspector_filter.h"
37 #include "core/components_ng/base/ui_node.h"
38 #include "core/components_ng/base/view_stack_processor.h"
39 #include "core/components_ng/event/gesture_event_hub.h"
40 #include "core/components_ng/layout/layout_property.h"
41 #include "core/components_ng/pattern/button/button_layout_property.h"
42 #include "core/components_ng/pattern/button/button_pattern.h"
43 #include "core/components_ng/pattern/divider/divider_layout_property.h"
44 #include "core/components_ng/pattern/divider/divider_model_ng.h"
45 #include "core/components_ng/pattern/divider/divider_pattern.h"
46 #include "core/components_ng/pattern/flex/flex_layout_algorithm.h"
47 #include "core/components_ng/pattern/flex/flex_layout_property.h"
48 #include "core/components_ng/pattern/image/image_pattern.h"
49 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
50 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
51 #include "core/components_ng/pattern/list/list_pattern.h"
52 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
53 #include "core/components_ng/pattern/overlay/dialog_manager.h"
54 #include "core/components_ng/pattern/overlay/overlay_manager.h"
55 #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h"
56 #include "core/components_ng/pattern/relative_container/relative_container_pattern.h"
57 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
58 #include "core/components_ng/pattern/stage/page_pattern.h"
59 #include "core/components_ng/pattern/text/text_layout_property.h"
60 #include "core/components_ng/pattern/text/text_pattern.h"
61 #include "core/components_ng/property/calc_length.h"
62 #include "core/components_ng/property/measure_property.h"
63 #include "core/components_v2/inspector/inspector_constants.h"
64 #include "core/event/key_event.h"
65 #include "core/event/touch_event.h"
66 #include "core/pipeline/base/element_register.h"
67 #include "core/pipeline_ng/pipeline_context.h"
68 
69 namespace OHOS::Ace::NG {
70 
71 namespace {
72 constexpr int32_t SHEET_INFO_IDX = -2;
73 constexpr Dimension SHEET_IMAGE_MARGIN = 16.0_vp;
74 constexpr Dimension SHEET_DIVIDER_WIDTH = 1.0_px;
75 constexpr Dimension SHEET_LIST_PADDING = 24.0_vp;
76 constexpr Color DEFAULT_BUTTON_COLOR = Color(0xff007dff);
77 const CalcLength SHEET_IMAGE_SIZE(40.0_vp);
78 constexpr int32_t THREE_BUTTON_MODE = 3;
79 constexpr int32_t TWO_BUTTON_MODE = 2;
80 constexpr int32_t ONE_BUTTON_MODE = 1;
81 constexpr int32_t START_CHILD_INDEX = 0;
82 constexpr uint32_t DIALOG_TITLE_MAXLINES = 1;
83 constexpr Dimension DIALOG_ONE_TITLE_ALL_HEIGHT = 56.0_vp;
84 constexpr Dimension DIALOG_TITLE_CONTENT_HEIGHT = 35.0_px;
85 constexpr int32_t DIALOG_TITLE_AVE_BY_2 = 2;
86 constexpr Dimension DIALOG_CONTENT_PADDING_TOP = 0.0_vp;
87 constexpr Dimension DIALOG_SUBTITLE_PADDING_LEFT = 24.0_vp;
88 constexpr Dimension DIALOG_SUBTITLE_PADDING_RIGHT = 24.0_vp;
89 constexpr Dimension DIALOG_TWO_TITLE_ZERO_SPACE = 0.0_vp;
90 constexpr Dimension ADAPT_TITLE_MIN_FONT_SIZE = 16.0_fp;
91 constexpr Dimension ADAPT_SUBTITLE_MIN_FONT_SIZE = 12.0_fp;
92 constexpr uint32_t ADAPT_TITLE_MAX_LINES = 2;
93 constexpr Dimension DIALOG_BUTTON_BORDER_RADIUS = 20.0_vp;
94 constexpr int32_t TEXT_ALIGN_TITLE_CENTER = 1;
95 constexpr int32_t BUTTON_TYPE_NORMAL = 1;
96 
GetBoolStr(bool isTure)97 std::string GetBoolStr(bool isTure)
98 {
99     return isTure ? "True" : "False";
100 }
101 } // namespace
102 
OnModifyDone()103 void DialogPattern::OnModifyDone()
104 {
105     Pattern::OnModifyDone();
106     auto host = GetHost();
107     CHECK_NULL_VOID(host);
108     auto gestureHub = host->GetOrCreateGestureEventHub();
109     CHECK_NULL_VOID(gestureHub);
110 
111     if (!onClick_) {
112         InitClickEvent(gestureHub);
113     }
114     auto focusHub = host->GetOrCreateFocusHub();
115     CHECK_NULL_VOID(focusHub);
116     RegisterOnKeyEvent(focusHub);
117     InitFocusEvent(focusHub);
118 }
119 
OnAttachToFrameNode()120 void DialogPattern::OnAttachToFrameNode()
121 {
122     auto host = GetHost();
123     CHECK_NULL_VOID(host);
124     auto pipelineContext = host->GetContext();
125     CHECK_NULL_VOID(pipelineContext);
126     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
127     InitHostWindowRect();
128     auto foldModeChangeCallback = [weak = WeakClaim(this)](FoldDisplayMode foldDisplayMode) {
129         auto pattern = weak.Upgrade();
130         CHECK_NULL_VOID(pattern);
131         pattern->isFoldStatusChanged_ = true;
132     };
133     auto callbackId = pipelineContext->RegisterFoldDisplayModeChangedCallback(std::move(foldModeChangeCallback));
134     UpdateFoldDisplayModeChangedCallbackId(callbackId);
135     RegisterHoverModeChangeCallback();
136     RegisterAvoidInfoChangeListener(host);
137 }
138 
RegisterHoverModeChangeCallback()139 void DialogPattern::RegisterHoverModeChangeCallback()
140 {
141     auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
142         auto pattern = weak.Upgrade();
143         CHECK_NULL_VOID(pattern);
144         auto host = pattern->GetHost();
145         CHECK_NULL_VOID(host);
146         auto context = host->GetContext();
147         CHECK_NULL_VOID(context);
148         AnimationOption optionPosition;
149         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
150         optionPosition.SetCurve(motion);
151         context->FlushUITasks();
152         context->Animate(optionPosition, motion, [host, context]() {
153             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
154             context->FlushUITasks();
155         });
156     };
157     auto host = GetHost();
158     CHECK_NULL_VOID(host);
159     auto context = host->GetContext();
160     CHECK_NULL_VOID(context);
161     auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
162     UpdateHoverModeChangedCallbackId(hoverModeCallId);
163 }
164 
OnDetachFromFrameNode(FrameNode * frameNode)165 void DialogPattern::OnDetachFromFrameNode(FrameNode* frameNode)
166 {
167     CHECK_NULL_VOID(frameNode);
168     auto pipeline = frameNode->GetContext();
169     CHECK_NULL_VOID(pipeline);
170     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
171     if (HasFoldDisplayModeChangedCallbackId()) {
172         pipeline->UnRegisterFoldDisplayModeChangedCallback(foldDisplayModeChangedCallbackId_.value_or(-1));
173     }
174     if (HasHoverModeChangedCallbackId()) {
175         pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
176     }
177     if (onWillDismissRelease_) {
178         onWillDismissRelease_();
179     }
180     UnRegisterAvoidInfoChangeListener(frameNode);
181 }
182 
OnFontConfigurationUpdate()183 void DialogPattern::OnFontConfigurationUpdate()
184 {
185     CHECK_NULL_VOID(buttonContainer_);
186     UpdatePropertyForElderly(dialogProperties_.buttons);
187     contentColumn_->RemoveChild(buttonContainer_);
188     auto buttonContainer = BuildButtons(dialogProperties_.buttons, dialogProperties_.buttonDirection);
189     CHECK_NULL_VOID(buttonContainer);
190     buttonContainer->MountToParent(contentColumn_);
191     UpdateTextFontScale();
192     if (isSuitableForElderly_ && NeedsButtonDirectionChange(dialogProperties_.buttons)) {
193         contentColumn_->RemoveChild(buttonContainer_);
194         auto buttonContainerNew = BuildButtons(dialogProperties_.buttons, DialogButtonDirection::VERTICAL);
195         CHECK_NULL_VOID(buttonContainerNew);
196         buttonContainerNew->MountToParent(contentColumn_);
197         buttonContainer_ = buttonContainerNew;
198         CheckScrollHeightIsNegative(contentColumn_, dialogProperties_);
199         UpdateTextFontScale();
200     }
201 }
202 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)203 void DialogPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
204 {
205     GestureEventFunc task = [weak = WeakClaim(this)](const GestureEvent& info) {
206         auto pattern = weak.Upgrade();
207         CHECK_NULL_VOID(pattern);
208         pattern->HandleClick(info);
209     };
210     onClick_ = MakeRefPtr<ClickEvent>(std::move(task));
211     gestureHub->AddClickEvent(onClick_);
212 }
213 
GetContentRect(const RefPtr<FrameNode> & contentNode)214 RectF DialogPattern::GetContentRect(const RefPtr<FrameNode>& contentNode)
215 {
216     auto contentRect = contentNode->GetGeometryNode()->GetFrameRect();
217     if (!dialogProperties_.customStyle) {
218         return contentRect;
219     }
220 
221     RefPtr<FrameNode> customContent;
222     auto customNode = customNode_.Upgrade();
223     while (customNode) {
224         customContent = DynamicCast<FrameNode>(customNode);
225         if (customContent) {
226             break;
227         }
228         customNode = customNode->GetChildAtIndex(0);
229     }
230     CHECK_NULL_RETURN(customContent, contentRect);
231 
232     auto customContentRect = customContent->GetGeometryNode()->GetFrameRect();
233     auto customContentX = contentRect.GetX() + customContentRect.GetX();
234     auto customContentY = contentRect.GetY() + customContentRect.GetY();
235     contentRect.SetRect(customContentX, customContentY, customContentRect.Width(), customContentRect.Height());
236     return contentRect;
237 }
238 
HandleClick(const GestureEvent & info)239 void DialogPattern::HandleClick(const GestureEvent& info)
240 {
241     if (info.GetSourceDevice() == SourceType::KEYBOARD) {
242         return;
243     }
244     auto host = GetHost();
245     CHECK_NULL_VOID(host);
246     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
247     CHECK_NULL_VOID(props);
248     auto globalOffset = host->GetPaintRectOffset(false, true);
249     auto autoCancel = props->GetAutoCancel().value_or(true);
250     if (autoCancel) {
251         auto content = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
252         CHECK_NULL_VOID(content);
253         auto contentRect = GetContentRect(content);
254         // close dialog if clicked outside content rect
255         auto&& clickPosition = info.GetGlobalLocation();
256         if (!contentRect.IsInRegion(
257             PointF(clickPosition.GetX() - globalOffset.GetX(), clickPosition.GetY() - globalOffset.GetY()))) {
258             auto overlayManager = GetOverlayManager(nullptr);
259             CHECK_NULL_VOID(overlayManager);
260             if (this->CallDismissInNDK(static_cast<int32_t>(DialogDismissReason::DIALOG_TOUCH_OUTSIDE))) {
261                 return;
262             } else if (this->ShouldDismiss()) {
263                 overlayManager->SetDismissDialogId(host->GetId());
264                 DialogManager::GetInstance().SetDismissDialogInfo(host->GetId(), host->GetTag());
265                 auto currentId = Container::CurrentId();
266                 this->CallOnWillDismiss(static_cast<int32_t>(DialogDismissReason::DIALOG_TOUCH_OUTSIDE), currentId);
267                 TAG_LOGI(AceLogTag::ACE_DIALOG, "Dialog Should Dismiss, currentId: %{public}d", currentId);
268                 return;
269             }
270 
271             PopDialog(-1);
272             if (overlayManager->isMaskNode(GetHost()->GetId())) {
273                 overlayManager->PopModalDialog(GetHost()->GetId());
274             }
275         }
276     }
277 }
278 
PopDialog(int32_t buttonIdx=-1)279 void DialogPattern::PopDialog(int32_t buttonIdx = -1)
280 {
281     auto host = GetHost();
282     CHECK_NULL_VOID(host);
283     auto overlayManager = GetOverlayManager(host);
284     CHECK_NULL_VOID(overlayManager);
285 
286     if (host->IsRemoving()) {
287         return;
288     }
289 
290     auto hub = host->GetOrCreateEventHub<DialogEventHub>();
291     if (buttonIdx != -1) {
292         hub->FireSuccessEvent(buttonIdx, host);
293         RecordEvent(buttonIdx);
294     } else {
295         // trigger onCancel callback
296         hub->FireCancelEvent();
297         RecordEvent(buttonIdx);
298     }
299     if (dialogProperties_.isShowInSubWindow) {
300         auto pipeline = host->GetContextRefPtr();
301         auto currentId = pipeline ? pipeline->GetInstanceId() : Container::CurrentId();
302         SubwindowManager::GetInstance()->DeleteHotAreas(currentId, host->GetId(), SubwindowType::TYPE_DIALOG);
303         SubwindowManager::GetInstance()->HideDialogSubWindow(currentId);
304     }
305     overlayManager->CloseDialog(host);
306 }
307 
RecordEvent(int32_t btnIndex) const308 void DialogPattern::RecordEvent(int32_t btnIndex) const
309 {
310     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
311         return;
312     }
313     std::string btnText;
314     if (btnIndex >= 0 && static_cast<size_t>(btnIndex) < dialogProperties_.buttons.size()) {
315         btnText = dialogProperties_.buttons.at(btnIndex).text;
316     }
317     Recorder::EventType eventType;
318     if (btnIndex == -1) {
319         eventType = Recorder::EventType::DIALOG_CANCEL;
320     } else {
321         eventType = Recorder::EventType::DIALOG_ACTION;
322     }
323     Recorder::EventParamsBuilder builder;
324     builder.SetEventType(eventType)
325         .SetText(btnText)
326         .SetExtra(Recorder::KEY_TITLE, title_)
327         .SetExtra(Recorder::KEY_SUB_TITLE, subtitle_);
328     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
329 }
330 
331 // set render context properties of content frame
UpdateContentRenderContext(const RefPtr<FrameNode> & contentNode,const DialogProperties & props)332 void DialogPattern::UpdateContentRenderContext(const RefPtr<FrameNode>& contentNode, const DialogProperties& props)
333 {
334     auto contentRenderContext = contentNode->GetRenderContext();
335     CHECK_NULL_VOID(contentRenderContext);
336     contentRenderContext_ = contentRenderContext;
337     auto pipeLineContext = contentNode->GetContextWithCheck();
338     CHECK_NULL_VOID(pipeLineContext);
339     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
340         contentRenderContext->IsUniRenderEnabled() && props.isSysBlurStyle) {
341         BlurStyleOption styleOption;
342         if (props.blurStyleOption.has_value()) {
343             styleOption = props.blurStyleOption.value();
344             if (styleOption.policy == BlurStyleActivePolicy::FOLLOWS_WINDOW_ACTIVE_STATE) {
345                 pipeLineContext->AddWindowFocusChangedCallback(contentNode->GetId());
346             } else {
347                 pipeLineContext->RemoveWindowFocusChangedCallback(contentNode->GetId());
348             }
349         }
350         styleOption.blurStyle = static_cast<BlurStyle>(
351             props.backgroundBlurStyle.value_or(dialogTheme_->GetDialogBackgroundBlurStyle()));
352         if (props.blurStyleOption.has_value() && contentRenderContext->GetBackgroundEffect().has_value()) {
353             contentRenderContext->UpdateBackgroundEffect(std::nullopt);
354         }
355         contentRenderContext->UpdateBackBlurStyle(styleOption);
356         if (props.effectOption.has_value()) {
357             if (props.effectOption->policy == BlurStyleActivePolicy::FOLLOWS_WINDOW_ACTIVE_STATE) {
358                 pipeLineContext->AddWindowFocusChangedCallback(contentNode->GetId());
359             } else {
360                 pipeLineContext->RemoveWindowFocusChangedCallback(contentNode->GetId());
361             }
362             if (contentRenderContext->GetBackBlurStyle().has_value()) {
363                 contentRenderContext->UpdateBackBlurStyle(std::nullopt);
364             }
365             contentRenderContext->UpdateBackgroundEffect(props.effectOption.value());
366         }
367         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(dialogTheme_->GetColorBgWithBlur()));
368     } else {
369         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(dialogTheme_->GetBackgroundColor()));
370     }
371     bool isCustomBorder = props.borderRadius.has_value() || props.borderWidth.has_value() ||
372         props.borderStyle.has_value() || props.borderColor.has_value();
373     BorderRadiusProperty radius;
374     if (props.borderRadius.has_value()) {
375         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE)) {
376             radius = props.borderRadius.value();
377             ParseBorderRadius(radius);
378             contentRenderContext->UpdateBorderRadius(radius);
379         } else {
380             contentRenderContext->UpdateBorderRadius(props.borderRadius.value());
381         }
382     } else {
383         radius.SetRadius(dialogTheme_->GetRadius().GetX());
384         contentRenderContext->UpdateBorderRadius(radius);
385         if (!isCustomBorder && dialogTheme_->GetDialogDoubleBorderEnable()) {
386             contentRenderContext->UpdateOuterBorderRadius(radius);
387         }
388     }
389     if (props.borderWidth.has_value()) {
390         auto layoutProps = contentNode->GetLayoutProperty<LinearLayoutProperty>();
391         CHECK_NULL_VOID(layoutProps);
392         layoutProps->UpdateBorderWidth(props.borderWidth.value());
393         contentRenderContext->UpdateBorderWidth(props.borderWidth.value());
394     } else {
395         BorderWidthProperty borderWidth;
396         if (!isCustomBorder && dialogTheme_->GetDialogDoubleBorderEnable()) {
397             auto layoutProps = contentNode->GetLayoutProperty<LinearLayoutProperty>();
398             CHECK_NULL_VOID(layoutProps);
399             borderWidth.SetBorderWidth(Dimension(dialogTheme_->GetDialogInnerBorderWidth()));
400             layoutProps->UpdateBorderWidth(borderWidth);
401             BorderWidthProperty outerWidthProp;
402             outerWidthProp.SetBorderWidth(Dimension(dialogTheme_->GetDialogOuterBorderWidth()));
403             contentRenderContext->UpdateOuterBorderWidth(outerWidthProp);
404         } else {
405             borderWidth.SetBorderWidth(dialogTheme_->GetBackgroudBorderWidth());
406             auto layoutProps = contentNode->GetLayoutProperty<LinearLayoutProperty>();
407             if (layoutProps) {
408                 layoutProps->UpdateBorderWidth(borderWidth);
409             }
410         }
411         contentRenderContext->UpdateBorderWidth(borderWidth);
412     }
413     contentNodeMap_[DialogContentNode::BORDERWIDTH] = contentNode;
414     if (props.borderStyle.has_value()) {
415         contentRenderContext->UpdateBorderStyle(props.borderStyle.value());
416     }
417     auto contentPattern = contentNode->GetPattern();
418     CHECK_NULL_VOID(contentPattern);
419     if (props.borderColor.has_value()) {
420         contentRenderContext->UpdateBorderColor(props.borderColor.value());
421         contentPattern->CheckLocalized();
422     } else {
423         BorderColorProperty borderColor;
424         if (!isCustomBorder && dialogTheme_->GetDialogDoubleBorderEnable()) {
425             borderColor.SetColor(dialogTheme_->GetDialogInnerBorderColor());
426             BorderColorProperty outerColorProp;
427             outerColorProp.SetColor(dialogTheme_->GetDialogOuterBorderColor());
428             contentRenderContext->UpdateOuterBorderColor(outerColorProp);
429         } else {
430             borderColor.SetColor(dialogTheme_->GetBackgroudBorderColor());
431         }
432         contentRenderContext->UpdateBorderColor(borderColor);
433     }
434     if (props.shadow.has_value()) {
435         contentRenderContext->UpdateBackShadow(props.shadow.value());
436     } else {
437         Shadow shadow = Shadow::CreateShadow(static_cast<ShadowStyle>(dialogTheme_->GetShadowDialog()));
438         contentRenderContext->UpdateBackShadow(shadow);
439     }
440     contentRenderContext->SetClipToBounds(true);
441 }
442 
ParseBorderRadius(BorderRadiusProperty & raidus)443 void DialogPattern::ParseBorderRadius(BorderRadiusProperty& raidus)
444 {
445     if (!raidus.radiusTopLeft.has_value() || raidus.radiusTopLeft.value().Value() < 0) {
446         raidus.radiusTopLeft = dialogTheme_->GetRadius().GetX();
447     }
448     if (!raidus.radiusTopRight.has_value() || raidus.radiusTopRight.value().Value() < 0) {
449         raidus.radiusTopRight = dialogTheme_->GetRadius().GetX();
450     }
451     if (!raidus.radiusBottomLeft.has_value() || raidus.radiusBottomLeft.value().Value() < 0) {
452         raidus.radiusBottomLeft = dialogTheme_->GetRadius().GetX();
453     }
454     if (!raidus.radiusBottomRight.has_value() || raidus.radiusBottomRight.value().Value() < 0) {
455         raidus.radiusBottomRight = dialogTheme_->GetRadius().GetX();
456     }
457 }
458 
CreateDialogScroll(const DialogProperties & dialogProps)459 RefPtr<FrameNode> DialogPattern::CreateDialogScroll(const DialogProperties& dialogProps)
460 {
461     auto scroll = FrameNode::CreateFrameNode(
462         V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
463     CHECK_NULL_RETURN(scroll, nullptr);
464     auto props = scroll->GetLayoutProperty<ScrollLayoutProperty>();
465     props->UpdateAxis(Axis::VERTICAL);
466     props->UpdateAlignment(Alignment::CENTER_LEFT);
467     // If title not exist, set scroll align center so that text align center.
468     auto scrollFlexAlign = dialogTheme_->GetScrollFlexAlign();
469     if ((dialogProps.title.empty() && dialogProps.subtitle.empty())) {
470         scrollFlexAlign = FlexAlign::CENTER;
471     }
472     props->UpdateAlignSelf(scrollFlexAlign);
473     return scroll;
474 }
475 
BuildChild(const DialogProperties & props)476 void DialogPattern::BuildChild(const DialogProperties& props)
477 {
478     UpdatePropertyForElderly(props.buttons);
479     // append customNode
480     auto customNode = customNode_.Upgrade();
481     if (customNode) {
482         BuildCustomChild(props, customNode);
483         return;
484     }
485     // Make dialog Content Column
486     auto contentColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
487         AceType::MakeRefPtr<LinearLayoutPattern>(true));
488     CHECK_NULL_VOID(contentColumn);
489     if (!props.title.empty() || !props.subtitle.empty()) {
490         auto title = BuildTitle(props);
491         CHECK_NULL_VOID(title);
492         titleContainer_ = title;
493         contentColumn->AddChild(title);
494     }
495 
496     if (!props.content.empty()) {
497         auto content = BuildContent(props);
498         CHECK_NULL_VOID(content);
499         // create a scroll
500         auto scroll = CreateDialogScroll(props);
501         CHECK_NULL_VOID(scroll);
502         content->MountToParent(scroll);
503         scroll->MountToParent(contentColumn);
504         scroll->MarkModifyDone();
505     }
506 
507     if (!props.customStyle) {
508         UpdateContentRenderContext(contentColumn, props);
509         if (props.height.has_value()) {
510             auto layoutProps = contentColumn->GetLayoutProperty<LinearLayoutProperty>();
511             CHECK_NULL_VOID(layoutProps);
512             layoutProps->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
513             layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
514         }
515     }
516 
517     auto columnProp = AceType::DynamicCast<LinearLayoutProperty>(contentColumn->GetLayoutProperty());
518     CHECK_NULL_VOID(columnProp);
519     // content is full screen in Watch mode
520     auto measureType = dialogTheme_->GetColumnMeasureType();
521     columnProp->UpdateMeasureType(measureType);
522 
523     // build ActionSheet child
524     if (props.type == DialogType::ACTION_SHEET && !props.sheetsInfo.empty()) {
525         auto sheetContainer = BuildSheet(props.sheetsInfo);
526         contentNodeMap_[DialogContentNode::SHEET] = sheetContainer;
527         CHECK_NULL_VOID(sheetContainer);
528         sheetContainer->MountToParent(contentColumn);
529         // scrollable
530         sheetContainer->MarkModifyDone();
531     }
532 
533     // Make Menu node if hasMenu (actionMenu)
534     if (props.isMenu) {
535         bool hasTitle = !props.title.empty() || !props.subtitle.empty();
536         auto menu = BuildMenu(props.buttons, hasTitle);
537         CHECK_NULL_VOID(menu);
538         menu->MountToParent(contentColumn);
539     } else {
540         // build buttons
541         if (!props.buttons.empty()) {
542             auto buttonContainer = BuildButtons(props.buttons, props.buttonDirection);
543             CHECK_NULL_VOID(buttonContainer);
544             buttonContainer->MountToParent(contentColumn);
545         }
546     }
547 
548     auto dialog = GetHost();
549     contentColumn->MountToParent(dialog);
550     AddExtraMaskNode(props);
551     UpdateTextFontScale();
552     if (isSuitableForElderly_ && NeedsButtonDirectionChange(props.buttons)) {
553         //remove buttonContainer when Button text is too long
554         contentColumn->RemoveChild(buttonContainer_);
555         auto buttonContainerNew = BuildButtons(props.buttons, DialogButtonDirection::VERTICAL);
556         buttonContainerNew->MountToParent(contentColumn);
557         buttonContainer_ = buttonContainerNew;
558         CheckScrollHeightIsNegative(contentColumn, props);
559     }
560     contentColumn_ = contentColumn;
561     UpdateTextFontScale();
562 }
563 
AddExtraMaskNode(const DialogProperties & props)564 void DialogPattern::AddExtraMaskNode(const DialogProperties& props)
565 {
566     auto dialog = GetHost();
567     CHECK_NULL_VOID(dialog);
568     auto pipeline = dialog->GetContext();
569     CHECK_NULL_VOID(pipeline);
570     auto dialogTheme = pipeline->GetTheme<DialogTheme>();
571     CHECK_NULL_VOID(dialogTheme);
572     auto needAddMaskNode = props.maskTransitionEffect != nullptr || props.dialogTransitionEffect != nullptr;
573     if (needAddMaskNode && props.isModal && !props.isShowInSubWindow) {
574         auto extraMaskNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
575             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
576         CHECK_NULL_VOID(extraMaskNode);
577         auto extraMaskNodeContext = extraMaskNode->GetRenderContext();
578         CHECK_NULL_VOID(extraMaskNodeContext);
579         auto maskLayoutProps = extraMaskNode->GetLayoutProperty<LinearLayoutProperty>();
580         CHECK_NULL_VOID(maskLayoutProps);
581         extraMaskNodeContext->UpdateBackgroundColor(props.maskColor.value_or(dialogTheme->GetMaskColorEnd()));
582         extraMaskNodeContext->UpdateZIndex(-1);
583         extraMaskNode->MountToParent(dialog);
584     }
585 }
586 
BuildCustomChild(const DialogProperties & props,const RefPtr<UINode> & customNode)587 void DialogPattern::BuildCustomChild(const DialogProperties& props, const RefPtr<UINode>& customNode)
588 {
589     auto contentWrapper = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
590         AceType::MakeRefPtr<LinearLayoutPattern>(true));
591     CHECK_NULL_VOID(contentWrapper);
592     if (!props.customStyle) {
593         UpdateContentRenderContext(contentWrapper, props);
594     }
595     customNode->MountToParent(contentWrapper);
596     auto dialog = GetHost();
597     contentWrapper->MountToParent(dialog);
598     AddExtraMaskNode(props);
599 }
600 
IsAlertDialog(const DialogProperties & props)601 bool IsAlertDialog(const DialogProperties& props)
602 {
603     return props.type == DialogType::ALERT_DIALOG && props.isAlertDialog;
604 }
605 
BuildMainTitle(const DialogProperties & dialogProperties)606 RefPtr<FrameNode> DialogPattern::BuildMainTitle(const DialogProperties& dialogProperties)
607 {
608     auto title = FrameNode::CreateFrameNode(
609         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
610     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(title->GetLayoutProperty());
611     CHECK_NULL_RETURN(titleProp, nullptr);
612     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
613     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
614     std::string titleContent = dialogProperties.title.empty() ? dialogProperties.subtitle : dialogProperties.title;
615     titleProp->UpdateContent(titleContent);
616     auto titleStyle = dialogTheme_->GetTitleTextStyle();
617     titleProp->UpdateFontSize(titleStyle.GetFontSize());
618     titleProp->UpdateFontWeight(titleStyle.GetFontWeight());
619     titleProp->UpdateTextColor(titleStyle.GetTextColor());
620     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
621         titleProp->UpdateAdaptMaxFontSize(dialogTheme_->GetTitleTextStyle().GetFontSize());
622         titleProp->UpdateAdaptMinFontSize(ADAPT_TITLE_MIN_FONT_SIZE);
623         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
624         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
625     }
626     PaddingProperty titlePadding;
627     auto paddingInTheme = (dialogProperties.content.empty() && dialogProperties.buttons.empty())
628                               ? dialogTheme_->GetTitleDefaultPadding()
629                               : dialogTheme_->GetTitleAdjustPadding();
630     titlePadding.left = CalcLength(paddingInTheme.Left());
631     titlePadding.right = CalcLength(paddingInTheme.Right());
632     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
633         titlePadding.top = CalcLength(dialogTheme_->GetPaddingTopTitle());
634         titlePadding.bottom = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
635     } else {
636         auto padding =
637             DIALOG_ONE_TITLE_ALL_HEIGHT - Dimension(DIALOG_TITLE_CONTENT_HEIGHT.ConvertToVp(), DimensionUnit::VP);
638         if (dialogTheme_->GetPaddingSingleTitle().ConvertToVp() > 0) {
639             padding = dialogTheme_->GetPaddingSingleTitle();
640         }
641         titlePadding.top = CalcLength(padding / DIALOG_TITLE_AVE_BY_2);
642         titlePadding.bottom = CalcLength(padding / DIALOG_TITLE_AVE_BY_2);
643     }
644     titleProp->UpdatePadding(titlePadding);
645     // XTS inspector value
646     title_ = dialogProperties.title;
647     subtitle_ = dialogProperties.subtitle;
648     auto titleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
649         AceType::MakeRefPtr<LinearLayoutPattern>(false));
650     CHECK_NULL_RETURN(titleRow, nullptr);
651     auto titleRowProps = titleRow->GetLayoutProperty<LinearLayoutProperty>();
652     CHECK_NULL_RETURN(titleRowProps, nullptr);
653     titleRowProps->UpdateMainAxisAlign(
654         dialogTheme_->GetTextAlignTitle() == TEXT_ALIGN_TITLE_CENTER ? FlexAlign::CENTER : FlexAlign::FLEX_START);
655     titleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
656     if (IsAlertDialog(dialogProperties)) {
657         titleProp->UpdateFontWeight(FontWeight::BOLD);
658         titleProp->UpdateTextAlign(TextAlign::CENTER);
659         titleProp->UpdateAdaptMinFontSize(dialogTheme_->GetTitleTextStyle().GetFontSize());
660         titleRowProps->UpdateMainAxisAlign(FlexAlign::CENTER);
661     }
662     title->MountToParent(titleRow);
663     title->MarkModifyDone();
664     contentNodeMap_[dialogProperties.title.empty() ? DialogContentNode::SUBTITLE : DialogContentNode::TITLE] = title;
665     auto focusHub = titleRow->GetFocusHub();
666     CHECK_NULL_RETURN(focusHub, titleRow);
667     focusHub->SetFocusable(false);
668     return titleRow;
669 }
670 
BuildSubTitle(const DialogProperties & dialogProperties)671 RefPtr<FrameNode> DialogPattern::BuildSubTitle(const DialogProperties& dialogProperties)
672 {
673     auto subtitle = FrameNode::CreateFrameNode(
674         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
675     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(subtitle->GetLayoutProperty());
676     CHECK_NULL_RETURN(titleProp, nullptr);
677     auto titleStyle = dialogTheme_->GetSubTitleTextStyle();
678     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
679     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
680     titleProp->UpdateContent(dialogProperties.subtitle);
681     titleProp->UpdateFontSize(titleStyle.GetFontSize());
682     titleProp->UpdateTextColor(titleStyle.GetTextColor());
683     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
684         titleProp->UpdateAdaptMaxFontSize(titleStyle.GetFontSize());
685         titleProp->UpdateAdaptMinFontSize(ADAPT_SUBTITLE_MIN_FONT_SIZE);
686         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
687         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
688     }
689     PaddingProperty titlePadding;
690     titlePadding.left = CalcLength(DIALOG_SUBTITLE_PADDING_LEFT);
691     titlePadding.right = CalcLength(DIALOG_SUBTITLE_PADDING_RIGHT);
692     titlePadding.top = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
693     titlePadding.bottom = CalcLength(dialogTheme_->GetPaddingTopTitle());
694     titleProp->UpdatePadding(titlePadding);
695 
696     // XTS inspector value
697     subtitle_ = dialogProperties.subtitle;
698 
699     auto subtitleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
700         AceType::MakeRefPtr<LinearLayoutPattern>(false));
701     CHECK_NULL_RETURN(subtitleRow, nullptr);
702     auto subtitleRowProps = subtitleRow->GetLayoutProperty<LinearLayoutProperty>();
703     CHECK_NULL_RETURN(subtitleRowProps, nullptr);
704     subtitleRowProps->UpdateMainAxisAlign(
705         dialogTheme_->GetTextAlignTitle() == TEXT_ALIGN_TITLE_CENTER ? FlexAlign::CENTER : FlexAlign::FLEX_START);
706     subtitleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
707     if (IsAlertDialog(dialogProperties)) {
708         titleProp->UpdateTextAlign(TextAlign::CENTER);
709         titleProp->UpdateAdaptMinFontSize(titleStyle.GetFontSize());
710         subtitleRowProps->UpdateMainAxisAlign(FlexAlign::CENTER);
711     }
712     subtitle->MountToParent(subtitleRow);
713     subtitle->MarkModifyDone();
714     contentNodeMap_[DialogContentNode::SUBTITLE] = subtitle;
715     return subtitleRow;
716 }
717 
BuildTitle(const DialogProperties & dialogProperties)718 RefPtr<FrameNode> DialogPattern::BuildTitle(const DialogProperties& dialogProperties)
719 {
720     auto titleRow = BuildMainTitle(dialogProperties);
721     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
722         auto titleColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
723             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
724         CHECK_NULL_RETURN(titleColumn, nullptr);
725         auto columnProps = titleColumn->GetLayoutProperty<LinearLayoutProperty>();
726         CHECK_NULL_RETURN(columnProps, nullptr);
727         columnProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
728         columnProps->UpdateMeasureType(MeasureType::MATCH_CONTENT);
729         auto subtitleRow = BuildSubTitle(dialogProperties);
730         titleColumn->AddChild(titleRow);
731         titleColumn->AddChild(subtitleRow);
732         return titleColumn;
733     }
734     return titleRow;
735 }
736 
BuildContent(const DialogProperties & props)737 RefPtr<FrameNode> DialogPattern::BuildContent(const DialogProperties& props)
738 {
739     // Make Content node
740     auto contentNode = FrameNode::CreateFrameNode(
741         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
742     auto contentProp = AceType::DynamicCast<TextLayoutProperty>(contentNode->GetLayoutProperty());
743     CHECK_NULL_RETURN(contentProp, nullptr);
744     // textAlign always align start. When text line count 1 and title doesn't exist, set text center position.
745     contentProp->UpdateTextAlign(TextAlign::START);
746     contentProp->UpdateContent(props.content);
747     auto contentStyle = dialogTheme_->GetContentTextStyle();
748     contentProp->UpdateFontSize(contentStyle.GetFontSize());
749     contentProp->UpdateTextColor(contentStyle.GetTextColor());
750     // update padding
751     Edge contentPaddingInTheme;
752     PaddingProperty contentPadding;
753     if (!props.title.empty() || !props.subtitle.empty()) {
754         contentPaddingInTheme =
755             props.buttons.empty() ? dialogTheme_->GetDefaultPadding() : dialogTheme_->GetAdjustPadding();
756         contentPadding.top = CalcLength(DIALOG_CONTENT_PADDING_TOP);
757     } else {
758         contentPaddingInTheme =
759             props.buttons.empty() ? dialogTheme_->GetContentDefaultPadding() : dialogTheme_->GetContentAdjustPadding();
760         contentPadding.top = CalcLength(contentPaddingInTheme.Top());
761     }
762     contentPadding.left = CalcLength(contentPaddingInTheme.Left());
763     contentPadding.right = CalcLength(contentPaddingInTheme.Right());
764     contentPadding.bottom = CalcLength(contentPaddingInTheme.Bottom());
765     contentProp->UpdatePadding(contentPadding);
766     if (IsAlertDialog(props)) {
767         contentProp->UpdateTextAlign(TextAlign::CENTER);
768         auto contentRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
769             AceType::MakeRefPtr<LinearLayoutPattern>(false));
770         CHECK_NULL_RETURN(contentRow, nullptr);
771         auto contentRowProps = contentRow->GetLayoutProperty<LinearLayoutProperty>();
772         CHECK_NULL_RETURN(contentRowProps, nullptr);
773         contentRowProps->UpdateMainAxisAlign(FlexAlign::CENTER);
774         contentRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
775         contentNode->MountToParent(contentRow);
776         message_ = props.content;
777         contentNode->MarkModifyDone();
778         contentNodeMap_[DialogContentNode::MESSAGE] = contentNode;
779         return contentRow;
780     }
781 
782     // XTS inspector value
783     message_ = props.content;
784     contentNode->MarkModifyDone();
785     contentNodeMap_[DialogContentNode::MESSAGE] = contentNode;
786     return contentNode;
787 }
788 
789 // to close dialog when clicked, use button index in Prompt to trigger success callback
BindCloseCallBack(const RefPtr<GestureEventHub> & hub,int32_t buttonIdx)790 void DialogPattern::BindCloseCallBack(const RefPtr<GestureEventHub>& hub, int32_t buttonIdx)
791 {
792     auto host = GetHost();
793     auto closeCallback = [weak = WeakClaim(RawPtr(host)), buttonIdx](GestureEvent& /*info*/) {
794         auto dialog = weak.Upgrade();
795         CHECK_NULL_VOID(dialog);
796         dialog->GetPattern<DialogPattern>()->PopDialog(buttonIdx);
797     };
798 
799     hub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
800 }
801 
ParseButtonFontColorAndBgColor(const ButtonInfo & params,std::string & textColor,std::optional<Color> & bgColor)802 void DialogPattern::ParseButtonFontColorAndBgColor(
803     const ButtonInfo& params, std::string& textColor, std::optional<Color>& bgColor)
804 {
805     // Parse Button Style
806     if (params.dlgButtonStyle.has_value()) {
807         switch (params.dlgButtonStyle.value()) {
808             case DialogButtonStyle::DEFAULT:
809                 textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
810                 bgColor = dialogTheme_->GetButtonDefaultBgColor();
811                 break;
812             case DialogButtonStyle::HIGHTLIGHT:
813                 textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
814                 bgColor = dialogTheme_->GetButtonHighlightBgColor();
815                 break;
816             default:
817                 break;
818         }
819     }
820 
821     // font color and background color
822     if (!params.textColor.empty()) {
823         textColor = params.textColor;
824     }
825     if (params.isBgColorSetted) {
826         bgColor = params.bgColor;
827     }
828 
829     // Parse default focus
830     bool isNormalButton = dialogTheme_->GetButtonType() == BUTTON_TYPE_NORMAL;
831     if (textColor.empty()) {
832         if (params.defaultFocus && isFirstDefaultFocus_ && !isNormalButton) {
833             textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
834         } else {
835             textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
836         }
837     }
838     if (!bgColor.has_value()) {
839         if (params.defaultFocus && isFirstDefaultFocus_ && !isNormalButton) {
840             bgColor = dialogTheme_->GetButtonHighlightBgColor();
841             isFirstDefaultFocus_ = false;
842         } else {
843             bgColor = dialogTheme_->GetButtonDefaultBgColor();
844         }
845     }
846 }
847 
CreateButton(const ButtonInfo & params,int32_t index,bool isCancel,bool isVertical,int32_t length)848 RefPtr<FrameNode> DialogPattern::CreateButton(
849     const ButtonInfo& params, int32_t index, bool isCancel, bool isVertical, int32_t length)
850 {
851     auto buttonNode = FrameNode::CreateFrameNode(
852         V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ButtonPattern>());
853     CHECK_NULL_RETURN(buttonNode, nullptr);
854     UpdateDialogButtonProperty(buttonNode, index, isVertical, length);
855     // parse button text color and background color
856     std::string textColor;
857     std::optional<Color> bgColor;
858     isFirstDefaultFocus_ = true;
859     ParseButtonFontColorAndBgColor(params, textColor, bgColor);
860     if ((dialogTheme_->GetButtonType() == BUTTON_TYPE_NORMAL) && params.dlgButtonStyle.has_value()) {
861         auto buttonStyle = params.dlgButtonStyle.value() == DialogButtonStyle::HIGHTLIGHT ? ButtonStyleMode::EMPHASIZE
862                                                                                           : ButtonStyleMode::NORMAL;
863         auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
864         CHECK_NULL_RETURN(buttonProp, nullptr);
865         buttonProp->UpdateButtonStyle(buttonStyle);
866     }
867 
868     // append text inside button
869     auto textNode = CreateButtonText(params.text, textColor);
870     CHECK_NULL_RETURN(textNode, nullptr);
871     textNode->MountToParent(buttonNode);
872     textNode->MarkModifyDone();
873     SetButtonEnabled(buttonNode, params.enabled);
874     auto hub = buttonNode->GetOrCreateGestureEventHub();
875     CHECK_NULL_RETURN(hub, nullptr);
876     // bind click event
877     if (params.action) {
878         hub->AddClickEvent(params.action);
879     }
880 
881     if (params.isPrimary) {
882         auto focusHub = buttonNode->GetFocusHub();
883         CHECK_NULL_RETURN(focusHub, nullptr);
884         focusHub->SetIsDefaultFocus(params.isPrimary);
885     }
886 
887     // to close dialog when clicked inside button rect
888     if (!isCancel) {
889         BindCloseCallBack(hub, index);
890     } else {
891         BindCloseCallBack(hub, -1);
892     }
893 
894     RegisterButtonOnKeyEvent(params, buttonNode, isCancel ? -1 : index);
895 
896     // add scale animation
897     auto inputHub = buttonNode->GetOrCreateInputEventHub();
898     CHECK_NULL_RETURN(inputHub, nullptr);
899     inputHub->SetHoverEffect(HoverEffectType::AUTO);
900 
901     // update background color
902     auto renderContext = buttonNode->GetRenderContext();
903     CHECK_NULL_RETURN(renderContext, nullptr);
904     renderContext->UpdateBackgroundColor(bgColor.value_or(Color::TRANSPARENT));
905 
906     // set button default height
907     auto layoutProps = buttonNode->GetLayoutProperty();
908     CHECK_NULL_RETURN(layoutProps, nullptr);
909     auto pipeline = buttonNode->GetContext();
910     CHECK_NULL_RETURN(pipeline, nullptr);
911     auto theme = pipeline->GetTheme<ButtonTheme>();
912     CHECK_NULL_RETURN(theme, nullptr);
913     if (!isSuitableForElderly_) {
914         layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(theme->GetHeight())));
915     }
916     return buttonNode;
917 }
918 
RegisterButtonOnKeyEvent(const ButtonInfo & params,RefPtr<FrameNode> & buttonNode,int32_t buttonIdx)919 void DialogPattern::RegisterButtonOnKeyEvent(const ButtonInfo& params, RefPtr<FrameNode>& buttonNode, int32_t buttonIdx)
920 {
921     auto focusHub = buttonNode->GetOrCreateFocusHub();
922     CHECK_NULL_VOID(focusHub);
923     auto host = GetHost();
924     CHECK_NULL_VOID(host);
925     auto onKeyEvent = [weak = WeakClaim(RawPtr(host)), params, buttonIdx](const KeyEvent& event) -> bool {
926         if ((event.code == KeyCode::KEY_SPACE || event.code == KeyCode::KEY_ENTER) &&
927             event.action == KeyAction::DOWN) {
928             auto dialog = weak.Upgrade();
929             CHECK_NULL_RETURN(dialog, false);
930             if (params.action) {
931                 auto actionFunc = params.action->GetGestureEventFunc();
932                 GestureEvent info;
933                 actionFunc(info);
934             }
935             dialog->GetPattern<DialogPattern>()->PopDialog(buttonIdx);
936             return true;
937         }
938         return false;
939     };
940     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
941 }
942 
UpdateDialogButtonProperty(RefPtr<FrameNode> & buttonNode,int32_t index,bool isVertical,int32_t length)943 void DialogPattern::UpdateDialogButtonProperty(
944     RefPtr<FrameNode>& buttonNode, int32_t index, bool isVertical, int32_t length)
945 {
946     // update button padding
947     auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
948     buttonProp->UpdateType(ButtonType::NORMAL);
949     if (dialogTheme_->GetButtonType() == BUTTON_TYPE_NORMAL) {
950         buttonProp->UpdateButtonStyle(ButtonStyleMode::NORMAL);
951     }
952     buttonProp->UpdateBorderRadius(BorderRadiusProperty(DIALOG_BUTTON_BORDER_RADIUS));
953     PaddingProperty buttonPadding;
954     buttonPadding.left = CalcLength(SHEET_LIST_PADDING);
955     buttonPadding.right = CalcLength(SHEET_LIST_PADDING);
956     buttonProp->UpdatePadding(buttonPadding);
957     if (!isVertical) {
958         // set flex grow to fill horizontal space
959         buttonProp->UpdateLayoutWeight(1);
960         buttonProp->UpdateFlexGrow(1.0);
961         buttonProp->UpdateFlexShrink(1.0);
962         if (isSuitableForElderly_ && index != 0) {
963             MarginProperty margin = {
964                 .left = CalcLength(dialogTheme_->GetMarginLeft()),
965             };
966             buttonProp->UpdateMargin(margin);
967         }
968     } else if (isVertical && index != (length - 1)) {
969         // update button space in vertical
970         auto buttonSpace = dialogTheme_->GetMutiButtonPaddingVertical();
971         MarginProperty margin = {
972             .bottom = CalcLength(buttonSpace),
973         };
974         buttonProp->UpdateMargin(margin);
975     }
976 }
977 
CreateDivider(const Dimension & dividerLength,const Dimension & dividerWidth,const Color & color,const Dimension & space)978 RefPtr<FrameNode> DialogPattern::CreateDivider(
979     const Dimension& dividerLength, const Dimension& dividerWidth, const Color& color, const Dimension& space)
980 {
981     auto dividerNode = FrameNode::CreateFrameNode(
982         V2::DIVIDER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<DividerPattern>());
983     CHECK_NULL_RETURN(dividerNode, nullptr);
984     auto dividerProps = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
985     CHECK_NULL_RETURN(dividerProps, nullptr);
986     dividerProps->UpdateVertical(true);
987     dividerProps->UpdateStrokeWidth(dividerWidth);
988     dividerProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(dividerLength)));
989     auto dividerPaintProps = dividerNode->GetPaintProperty<DividerRenderProperty>();
990     CHECK_NULL_RETURN(dividerPaintProps, nullptr);
991     dividerPaintProps->UpdateDividerColor(color);
992     // add divider margin
993     MarginProperty margin = {
994         .left = CalcLength((space - dividerWidth) / 2),
995         .right = CalcLength((space - dividerWidth) / 2),
996     };
997     dividerProps->UpdateMargin(margin);
998     return dividerNode;
999 }
1000 
1001 // alert dialog buttons
BuildButtons(const std::vector<ButtonInfo> & buttons,const DialogButtonDirection & direction)1002 RefPtr<FrameNode> DialogPattern::BuildButtons(
1003     const std::vector<ButtonInfo>& buttons, const DialogButtonDirection& direction)
1004 {
1005     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
1006     RefPtr<FrameNode> container;
1007     bool isVertical;
1008     if (direction == DialogButtonDirection::HORIZONTAL ||
1009         (direction == DialogButtonDirection::AUTO && buttons.size() == TWO_BUTTON_MODE)) {
1010         // use horizontal layout
1011         isVertical = false;
1012         container = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(false));
1013         CHECK_NULL_RETURN(container, nullptr);
1014         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
1015         layoutProps->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
1016         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
1017     } else {
1018         // use vertical layout
1019         isVertical = true;
1020         container = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(true));
1021         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
1022         layoutProps->UpdateCrossAxisAlign(FlexAlign::STRETCH);
1023         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
1024     }
1025     CHECK_NULL_RETURN(container, nullptr);
1026     // set action's padding
1027     PaddingProperty actionPadding;
1028     if (buttons.size() == ONE_BUTTON_MODE || isVertical) {
1029         actionPadding.left = CalcLength(dialogTheme_->GetSingleButtonPaddingStart());
1030         actionPadding.right = CalcLength(dialogTheme_->GetSingleButtonPaddingEnd());
1031     } else {
1032         actionPadding.left = CalcLength(dialogTheme_->GetMutiButtonPaddingStart());
1033         actionPadding.right = CalcLength(dialogTheme_->GetMutiButtonPaddingEnd());
1034     }
1035     auto padding = dialogTheme_->GetActionsPadding();
1036     actionPadding.top = CalcLength(dialogTheme_->GetButtonWithContentPadding());
1037     actionPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
1038     container->GetLayoutProperty()->UpdatePadding(actionPadding);
1039     AddButtonAndDivider(buttons, container, isVertical);
1040     container->MarkModifyDone();
1041     buttonContainer_ = container;
1042     return container;
1043 }
1044 
AddButtonAndDivider(const std::vector<ButtonInfo> & buttons,const RefPtr<NG::FrameNode> & container,bool isVertical)1045 void DialogPattern::AddButtonAndDivider(
1046     const std::vector<ButtonInfo>& buttons, const RefPtr<NG::FrameNode>& container, bool isVertical)
1047 {
1048     auto dividerLength = dialogTheme_->GetDividerLength();
1049     auto dividerWidth = dialogTheme_->GetDividerBetweenButtonWidth_();
1050     auto dividerColor = dialogTheme_->GetDividerColor();
1051     auto buttonSpace = dialogTheme_->GetMutiButtonPaddingHorizontal();
1052     auto length = buttons.size();
1053     for (size_t i = 0; i < length; ++i) {
1054         if (i != 0 && !isVertical && !isSuitableForElderly_) {
1055             auto dividerNode = CreateDivider(dividerLength, dividerWidth, dividerColor, buttonSpace);
1056             CHECK_NULL_VOID(dividerNode);
1057             container->AddChild(dividerNode);
1058         }
1059         auto buttonNode = CreateButton(buttons[i], i, false, isVertical, length);
1060         CHECK_NULL_VOID(buttonNode);
1061         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
1062         CHECK_NULL_VOID(buttonPattern);
1063         buttonPattern->SetSkipColorConfigurationUpdate();
1064         buttonNode->MountToParent(container);
1065         buttonNode->MarkModifyDone();
1066     }
1067 }
1068 
CreateButtonText(const std::string & text,const std::string & colorStr)1069 RefPtr<FrameNode> DialogPattern::CreateButtonText(const std::string& text, const std::string& colorStr)
1070 {
1071     auto textNode = FrameNode::CreateFrameNode(
1072         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
1073     CHECK_NULL_RETURN(textNode, nullptr);
1074     textNode->GetOrCreateFocusHub()->SetFocusable(true);
1075     auto textProps = textNode->GetLayoutProperty<TextLayoutProperty>();
1076     CHECK_NULL_RETURN(textProps, nullptr);
1077     textProps->UpdateContent(text);
1078     textProps->UpdateFontWeight(FontWeight::MEDIUM);
1079     textProps->UpdateMaxLines(1);
1080     textProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
1081     Dimension buttonTextSize = dialogTheme_->GetButtonTextSize().IsValid() ? dialogTheme_->GetButtonTextSize()
1082                                                                            : dialogTheme_->GetNormalButtonFontSize();
1083     textProps->UpdateFontSize(buttonTextSize);
1084 
1085     // update text color
1086     Color color;
1087     if (Color::ParseColorString(colorStr, color)) {
1088         textProps->UpdateTextColor(color);
1089     } else {
1090         textProps->UpdateTextColor(DEFAULT_BUTTON_COLOR);
1091     }
1092     auto host = GetHost();
1093     CHECK_NULL_RETURN(host, textNode);
1094     auto context = host->GetContext();
1095     CHECK_NULL_RETURN(context, textNode);
1096     auto textTheme = context->GetTheme<TextTheme>();
1097     CHECK_NULL_RETURN(textTheme, textNode);
1098     if (textTheme->GetIsTextFadeout()) {
1099         textProps->UpdateTextOverflow(TextOverflow::MARQUEE);
1100         textProps->UpdateTextMarqueeStartPolicy(MarqueeStartPolicy::ON_FOCUS);
1101         textProps->UpdateTextMarqueeFadeout(true);
1102     }
1103     return textNode;
1104 }
1105 
BuildSheetItem(const ActionSheetInfo & item)1106 RefPtr<FrameNode> DialogPattern::BuildSheetItem(const ActionSheetInfo& item)
1107 {
1108     // ListItem -> Row -> title + icon
1109     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
1110     RefPtr<FrameNode> itemNode = FrameNode::CreateFrameNode(
1111         V2::LIST_ITEM_ETS_TAG, Id, AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE));
1112     CHECK_NULL_RETURN(itemNode, nullptr);
1113 
1114     // update sheet row flex align
1115     auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
1116     auto itemRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
1117     CHECK_NULL_RETURN(itemRow, nullptr);
1118     auto layoutProps = itemRow->GetLayoutProperty<LinearLayoutProperty>();
1119     layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
1120     layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
1121 
1122     // mount icon
1123     if (!item.icon.empty()) {
1124         auto iconNode = BuildSheetInfoIcon(item.icon);
1125         iconNode->MountToParent(itemRow);
1126         iconNode->MarkModifyDone();
1127     }
1128 
1129     // mount title
1130     if (!item.title.empty()) {
1131         auto titleNode = BuildSheetInfoTitle(item.title);
1132         titleNode->MountToParent(itemRow);
1133         titleNode->MarkModifyDone();
1134     }
1135 
1136     // set sheetItem action
1137     auto hub = itemRow->GetOrCreateGestureEventHub();
1138     if (item.action) {
1139         hub->AddClickEvent(item.action);
1140         auto recordEvent = [weak = WeakClaim(this), title = item.title](GestureEvent& info) {
1141             if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1142                 return;
1143             }
1144             auto pattern = weak.Upgrade();
1145             CHECK_NULL_VOID(pattern);
1146             Recorder::EventParamsBuilder builder;
1147             builder.SetEventType(Recorder::EventType::DIALOG_SELECT)
1148                 .SetText(title)
1149                 .SetExtra(Recorder::KEY_TITLE, pattern->title_)
1150                 .SetExtra(Recorder::KEY_SUB_TITLE, pattern->subtitle_);
1151             Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1152         };
1153         auto recordEventPtr = MakeRefPtr<ClickEvent>(std::move(recordEvent));
1154         hub->AddClickEvent(recordEventPtr);
1155     }
1156 
1157     // close dialog when clicked
1158     BindCloseCallBack(hub, SHEET_INFO_IDX);
1159     itemRow->MountToParent(itemNode);
1160     return itemNode;
1161 }
1162 
BuildSheetInfoTitle(const std::string & title)1163 RefPtr<FrameNode> DialogPattern::BuildSheetInfoTitle(const std::string& title)
1164 {
1165     auto titleId = ElementRegister::GetInstance()->MakeUniqueId();
1166     auto titleNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, titleId, AceType::MakeRefPtr<TextPattern>());
1167     CHECK_NULL_RETURN(titleNode, nullptr);
1168     // update text style
1169     auto style = dialogTheme_->GetContentTextStyle();
1170     auto props = titleNode->GetLayoutProperty<TextLayoutProperty>();
1171     props->UpdateContent(title);
1172     props->UpdateTextOverflow(TextOverflow::ELLIPSIS);
1173     props->UpdateAdaptMaxFontSize(style.GetFontSize());
1174     props->UpdateAdaptMinFontSize(dialogTheme_->GetTitleMinFontSize());
1175     props->UpdateMaxLines(style.GetMaxLines());
1176     props->UpdateFlexGrow(1.0f);
1177     props->UpdateFlexShrink(1.0f);
1178     return titleNode;
1179 }
1180 
BuildSheetInfoIcon(const std::string & icon)1181 RefPtr<FrameNode> DialogPattern::BuildSheetInfoIcon(const std::string& icon)
1182 {
1183     auto iconId = ElementRegister::GetInstance()->MakeUniqueId();
1184     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, iconId, AceType::MakeRefPtr<ImagePattern>());
1185     CHECK_NULL_RETURN(iconNode, nullptr);
1186     // add image margin
1187     MarginProperty margin = {
1188         .left = CalcLength(SHEET_IMAGE_MARGIN),
1189         .right = CalcLength(SHEET_IMAGE_MARGIN),
1190         .top = CalcLength(SHEET_IMAGE_MARGIN),
1191         .bottom = CalcLength(SHEET_IMAGE_MARGIN),
1192     };
1193     auto iconProps = iconNode->GetLayoutProperty<ImageLayoutProperty>();
1194     iconProps->UpdateMargin(margin);
1195     auto imageSrc = ImageSourceInfo(icon);
1196     iconProps->UpdateImageSourceInfo(imageSrc);
1197     iconProps->UpdateUserDefinedIdealSize(CalcSize(SHEET_IMAGE_SIZE, SHEET_IMAGE_SIZE));
1198     return iconNode;
1199 }
1200 
BuildSheet(const std::vector<ActionSheetInfo> & sheets)1201 RefPtr<FrameNode> DialogPattern::BuildSheet(const std::vector<ActionSheetInfo>& sheets)
1202 {
1203     auto listId = ElementRegister::GetInstance()->MakeUniqueId();
1204     auto list = FrameNode::CreateFrameNode(V2::LIST_ETS_TAG, listId, AceType::MakeRefPtr<ListPattern>());
1205     CHECK_NULL_RETURN(list, nullptr);
1206 
1207     // set sheet padding
1208     CalcLength padding(SHEET_LIST_PADDING.ConvertToPx());
1209     PaddingProperty sheetPadding = {
1210         .left = padding,
1211         .right = padding,
1212         .top = padding,
1213         .bottom = padding,
1214     };
1215     list->GetLayoutProperty()->UpdatePadding(sheetPadding);
1216     list->GetPaintProperty<ScrollablePaintProperty>()->UpdateScrollBarMode(DisplayMode::OFF);
1217 
1218     for (auto&& item : sheets) {
1219         auto itemNode = BuildSheetItem(item);
1220         CHECK_NULL_RETURN(itemNode, nullptr);
1221         list->AddChild(itemNode);
1222     }
1223 
1224     // set list divider
1225     auto divider = V2::ItemDivider {
1226         .strokeWidth = SHEET_DIVIDER_WIDTH,
1227         .color = Color::GRAY,
1228     };
1229     auto props = list->GetLayoutProperty<ListLayoutProperty>();
1230     props->UpdateDivider(divider);
1231     props->UpdateListDirection(Axis::VERTICAL);
1232     return list;
1233 }
1234 
BuildMenu(const std::vector<ButtonInfo> & buttons,bool hasTitle)1235 RefPtr<FrameNode> DialogPattern::BuildMenu(const std::vector<ButtonInfo>& buttons, bool hasTitle)
1236 {
1237     auto menu = FrameNode::CreateFrameNode(
1238         V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(true));
1239     menuNode_ = menu;
1240     // column -> button
1241     const size_t size = buttons.size();
1242     for (size_t i = 0; i < size; ++i) {
1243         RefPtr<FrameNode> button;
1244         uint32_t val = size > 0 ? size - 1 : 0;
1245         if (i != val) {
1246             button = CreateButton(buttons[i], i, false, isSuitableForElderly_, size);
1247         } else {
1248             button = CreateButton(buttons[i], i, true, isSuitableForElderly_, size);
1249         }
1250         CHECK_NULL_RETURN(button, nullptr);
1251         auto props = DynamicCast<FrameNode>(button)->GetLayoutProperty();
1252         auto buttonRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1253             AceType::MakeRefPtr<LinearLayoutPattern>(isSuitableForElderly_));
1254         CHECK_NULL_RETURN(buttonRow, nullptr);
1255         auto buttonRowProps = buttonRow->GetLayoutProperty<LinearLayoutProperty>();
1256         CHECK_NULL_RETURN(buttonRowProps, nullptr);
1257         if (isSuitableForElderly_) {
1258             buttonRowProps->UpdateCrossAxisAlign(FlexAlign::STRETCH);
1259             buttonRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
1260         } else {
1261             buttonRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
1262             buttonRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
1263         }
1264 
1265         button->MountToParent(buttonRow);
1266         button->MarkModifyDone();
1267         menu->AddChild(buttonRow);
1268     }
1269     auto menuProps = menu->GetLayoutProperty<LinearLayoutProperty>();
1270     CHECK_NULL_RETURN(menuProps, nullptr);
1271     PaddingProperty menuPadding;
1272     if (!hasTitle) {
1273         menuPadding.top = CalcLength(dialogTheme_->GetContentAdjustPadding().Top());
1274     }
1275     menuPadding.left = CalcLength(dialogTheme_->GetDefaultPadding().Left());
1276     menuPadding.right = CalcLength(dialogTheme_->GetDefaultPadding().Right());
1277     menuPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
1278     menuProps->UpdatePadding(menuPadding);
1279     return menu;
1280 }
1281 
RegisterOnKeyEvent(const RefPtr<FocusHub> & focusHub)1282 void DialogPattern::RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1283 {
1284     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1285         auto pattern = wp.Upgrade();
1286         CHECK_NULL_RETURN(pattern, false);
1287         return pattern->OnKeyEvent(event);
1288     };
1289     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1290 }
1291 
OnKeyEvent(const KeyEvent & event)1292 bool DialogPattern::OnKeyEvent(const KeyEvent& event)
1293 {
1294     if (event.action != KeyAction::DOWN) {
1295         return false;
1296     }
1297     return false;
1298 }
1299 
InitFocusEvent(const RefPtr<FocusHub> & focusHub)1300 void DialogPattern::InitFocusEvent(const RefPtr<FocusHub>& focusHub)
1301 {
1302     auto onFocus = [wp = WeakClaim(this)](FocusReason reason) {
1303         auto pattern = wp.Upgrade();
1304         CHECK_NULL_VOID(pattern);
1305         pattern->HandleFocusEvent();
1306     };
1307     focusHub->SetOnFocusInternal(std::move(onFocus));
1308 
1309     auto onBlur = [wp = WeakClaim(this)]() {
1310         auto pattern = wp.Upgrade();
1311         CHECK_NULL_VOID(pattern);
1312         pattern->HandleBlurEvent();
1313     };
1314     focusHub->SetOnBlurInternal(std::move(onBlur));
1315 }
1316 
GetDefaultShadow(ShadowStyle style,const RefPtr<FrameNode> & frameNode)1317 Shadow GetDefaultShadow(ShadowStyle style, const RefPtr<FrameNode>& frameNode)
1318 {
1319     Shadow shadow = Shadow::CreateShadow(ShadowStyle::None);
1320     CHECK_NULL_RETURN(frameNode, shadow);
1321     auto pipeline = frameNode->GetContextRefPtr();
1322     CHECK_NULL_RETURN(pipeline, shadow);
1323     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
1324     CHECK_NULL_RETURN(shadowTheme, shadow);
1325     auto colorMode = pipeline->GetColorMode();
1326     shadow = shadowTheme->GetShadow(style, colorMode);
1327     return shadow;
1328 }
1329 
HandleBlurEvent()1330 void DialogPattern::HandleBlurEvent()
1331 {
1332     auto host = GetHost();
1333     CHECK_NULL_VOID(host);
1334     CHECK_NULL_VOID(contentRenderContext_ && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE));
1335     auto defaultShadowOff = static_cast<ShadowStyle>(dialogTheme_->GetDefaultShadowOff());
1336     contentRenderContext_->UpdateBackShadow(
1337         dialogProperties_.shadow.value_or(GetDefaultShadow(defaultShadowOff, host)));
1338 }
1339 
HandleFocusEvent()1340 void DialogPattern::HandleFocusEvent()
1341 {
1342     auto host = GetHost();
1343     CHECK_NULL_VOID(host);
1344     CHECK_NULL_VOID(contentRenderContext_ && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE));
1345     auto defaultShadowOn = static_cast<ShadowStyle>(dialogTheme_->GetDefaultShadowOn());
1346     contentRenderContext_->UpdateBackShadow(
1347         dialogProperties_.shadow.value_or(GetDefaultShadow(defaultShadowOn, host)));
1348 }
1349 
1350 // XTS inspector
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1351 void DialogPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1352 {
1353     /* no fixed attr below, just return */
1354     if (filter.IsFastFilter()) {
1355         return;
1356     }
1357     auto host = GetHost();
1358     CHECK_NULL_VOID(host);
1359     if (host->GetTag() == V2::ALERT_DIALOG_ETS_TAG || host->GetTag() == V2::ACTION_SHEET_DIALOG_ETS_TAG) {
1360         json->PutExtAttr("title", title_.c_str(), filter);
1361         json->PutExtAttr("subtitle", subtitle_.c_str(), filter);
1362         json->PutExtAttr("message", message_.c_str(), filter);
1363     }
1364     auto context = host->GetRenderContext();
1365     CHECK_NULL_VOID(context);
1366     json->PutExtAttr("uniRender", context->IsUniRenderEnabled() ? "true" : "false", filter);
1367 }
1368 
OnColorConfigurationUpdate()1369 void DialogPattern::OnColorConfigurationUpdate()
1370 {
1371     auto host = GetHost();
1372     CHECK_NULL_VOID(host);
1373     auto context = host->GetContext();
1374     CHECK_NULL_VOID(context);
1375     auto dialogTheme = context->GetTheme<DialogTheme>();
1376     CHECK_NULL_VOID(dialogTheme);
1377     dialogTheme_ = dialogTheme;
1378     UpdateTitleAndContentColor();
1379     UpdateWrapperBackgroundStyle(host, dialogTheme);
1380     UpdateButtonsProperty();
1381     OnModifyDone();
1382     host->MarkDirtyNode();
1383 }
1384 
UpdateTitleAndContentColor()1385 void DialogPattern::UpdateTitleAndContentColor()
1386 {
1387     CHECK_NULL_VOID(dialogTheme_);
1388     if (!dialogProperties_.title.empty() && contentNodeMap_.find(DialogContentNode::TITLE) != contentNodeMap_.end()) {
1389         UpdateDialogTextColor(contentNodeMap_[DialogContentNode::TITLE], dialogTheme_->GetTitleTextStyle());
1390     }
1391     if (!dialogProperties_.subtitle.empty() &&
1392         contentNodeMap_.find(DialogContentNode::SUBTITLE) != contentNodeMap_.end()) {
1393         UpdateDialogTextColor(contentNodeMap_[DialogContentNode::SUBTITLE],
1394             dialogProperties_.title.empty() ? dialogTheme_->GetTitleTextStyle() : dialogTheme_->GetSubTitleTextStyle());
1395     }
1396     if (!dialogProperties_.content.empty() &&
1397         contentNodeMap_.find(DialogContentNode::MESSAGE) != contentNodeMap_.end()) {
1398         UpdateDialogTextColor(contentNodeMap_[DialogContentNode::MESSAGE], dialogTheme_->GetContentTextStyle());
1399     }
1400 }
1401 
UpdateDialogTextColor(const RefPtr<FrameNode> & textNode,const TextStyle & textStyle)1402 void DialogPattern::UpdateDialogTextColor(const RefPtr<FrameNode>& textNode, const TextStyle& textStyle)
1403 {
1404     CHECK_NULL_VOID(textNode);
1405     auto textProps = AceType::DynamicCast<TextLayoutProperty>(textNode->GetLayoutProperty());
1406     CHECK_NULL_VOID(textProps);
1407     textProps->UpdateTextColor(textStyle.GetTextColor());
1408     textNode->MarkModifyDone();
1409 }
1410 
UpdateAlignmentAndOffset()1411 void DialogPattern::UpdateAlignmentAndOffset()
1412 {
1413     auto host = GetHost();
1414     CHECK_NULL_VOID(host);
1415     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1416     CHECK_NULL_VOID(props);
1417     auto dialogProp = GetDialogProperties();
1418     props->UpdateDialogAlignment(dialogProp.alignment);
1419     props->UpdateDialogOffset(dialogProp.offset);
1420 }
1421 
OnLanguageConfigurationUpdate()1422 void DialogPattern::OnLanguageConfigurationUpdate()
1423 {
1424     CHECK_NULL_VOID(dialogProperties_.onLanguageChange);
1425     dialogProperties_.onLanguageChange(dialogProperties_);
1426     UpdateAlignmentAndOffset();
1427     if (!dialogProperties_.title.empty() && contentNodeMap_.find(DialogContentNode::TITLE) != contentNodeMap_.end()) {
1428         UpdateNodeContent(contentNodeMap_[DialogContentNode::TITLE], dialogProperties_.title);
1429         title_ = dialogProperties_.title;
1430     }
1431 
1432     if (!dialogProperties_.subtitle.empty() &&
1433         contentNodeMap_.find(DialogContentNode::SUBTITLE) != contentNodeMap_.end()) {
1434         UpdateNodeContent(contentNodeMap_[DialogContentNode::SUBTITLE], dialogProperties_.subtitle);
1435         subtitle_ = dialogProperties_.subtitle;
1436     }
1437 
1438     if (!dialogProperties_.content.empty() &&
1439         contentNodeMap_.find(DialogContentNode::MESSAGE) != contentNodeMap_.end()) {
1440         UpdateNodeContent(contentNodeMap_[DialogContentNode::MESSAGE], dialogProperties_.content);
1441         message_ = dialogProperties_.content;
1442     }
1443 
1444     if (!dialogProperties_.buttons.empty()) {
1445         UpdateButtonsProperty();
1446     }
1447 
1448     if (dialogProperties_.type == DialogType::ACTION_SHEET) {
1449         UpdateSheetIconAndText();
1450     }
1451 
1452     if (dialogProperties_.shadow.has_value()) {
1453         contentRenderContext_->UpdateBackShadow(dialogProperties_.shadow.value());
1454     }
1455 
1456     if (dialogProperties_.borderWidth.has_value() &&
1457         contentNodeMap_.find(DialogContentNode::BORDERWIDTH) != contentNodeMap_.end()) {
1458         auto layoutProps = contentNodeMap_[DialogContentNode::BORDERWIDTH]->GetLayoutProperty<LinearLayoutProperty>();
1459         layoutProps->UpdateBorderWidth(dialogProperties_.borderWidth.value());
1460         contentRenderContext_->UpdateBorderWidth(dialogProperties_.borderWidth.value());
1461     }
1462 
1463     if (dialogProperties_.borderColor.has_value()) {
1464         auto contentNode = contentRenderContext_->GetHost();
1465         CHECK_NULL_VOID(contentNode);
1466         auto contentPattern = contentNode->GetPattern();
1467         CHECK_NULL_VOID(contentPattern);
1468         contentRenderContext_->UpdateBorderColor(dialogProperties_.borderColor.value());
1469         contentPattern->CheckLocalized();
1470     }
1471 
1472     if (dialogProperties_.borderRadius.has_value()) {
1473         contentRenderContext_->UpdateBorderRadius(dialogProperties_.borderRadius.value());
1474     }
1475 }
1476 
UpdateNodeContent(const RefPtr<FrameNode> & node,std::string & text)1477 void DialogPattern::UpdateNodeContent(const RefPtr<FrameNode>& node, std::string& text)
1478 {
1479     CHECK_NULL_VOID(node);
1480     auto layoutProps = AceType::DynamicCast<TextLayoutProperty>(node->GetLayoutProperty());
1481     CHECK_NULL_VOID(layoutProps);
1482     layoutProps->UpdateContent(text);
1483     node->MarkModifyDone();
1484 }
1485 
UpdateSheetIconAndText()1486 void DialogPattern::UpdateSheetIconAndText()
1487 {
1488     if (dialogProperties_.sheetsInfo.empty()) {
1489         return;
1490     }
1491 
1492     auto sheetContainer = contentNodeMap_[DialogContentNode::SHEET];
1493     CHECK_NULL_VOID(sheetContainer);
1494     int32_t sheetIndex = 0;
1495     for (const auto& sheet : sheetContainer->GetChildren()) {
1496         auto itemRow = DynamicCast<FrameNode>(sheet->GetFirstChild());
1497         CHECK_NULL_VOID(itemRow);
1498 
1499         auto sheetInfo = dialogProperties_.sheetsInfo.at(sheetIndex);
1500         if (!sheetInfo.icon.empty()) {
1501             auto iconNode = DynamicCast<FrameNode>(itemRow->GetFirstChild());
1502             CHECK_NULL_VOID(iconNode);
1503             auto iconProps = iconNode->GetLayoutProperty<ImageLayoutProperty>();
1504             CHECK_NULL_VOID(iconProps);
1505             iconProps->UpdateImageSourceInfo(ImageSourceInfo(sheetInfo.icon));
1506             iconNode->MarkModifyDone();
1507         }
1508         if (!sheetInfo.title.empty()) {
1509             auto titleNode = DynamicCast<FrameNode>(itemRow->GetLastChild());
1510             CHECK_NULL_VOID(titleNode);
1511             auto titleProps = titleNode->GetLayoutProperty<TextLayoutProperty>();
1512             CHECK_NULL_VOID(titleProps);
1513             titleProps->UpdateContent(sheetInfo.title);
1514             titleNode->MarkModifyDone();
1515         }
1516         ++sheetIndex;
1517     }
1518 }
1519 
UpdateButtonsPropertyForEachButton(RefPtr<FrameNode> buttonFrameNode,int32_t btnIndex)1520 void DialogPattern::UpdateButtonsPropertyForEachButton(RefPtr<FrameNode> buttonFrameNode, int32_t btnIndex)
1521 {
1522     CHECK_NULL_VOID(buttonFrameNode);
1523     auto pattern = buttonFrameNode->GetPattern<ButtonPattern>();
1524     CHECK_NULL_VOID(pattern);
1525     pattern->SetSkipColorConfigurationUpdate();
1526     // parse button text color and background color
1527     std::string textColorStr;
1528     std::optional<Color> bgColor;
1529     ParseButtonFontColorAndBgColor(dialogProperties_.buttons[btnIndex], textColorStr, bgColor);
1530     // update background color
1531     auto renderContext = buttonFrameNode->GetRenderContext();
1532     CHECK_NULL_VOID(renderContext);
1533     renderContext->UpdateBackgroundColor(bgColor.value_or(Color::TRANSPARENT));
1534     auto buttonTextNode = DynamicCast<FrameNode>(buttonFrameNode->GetFirstChild());
1535     CHECK_NULL_VOID(buttonTextNode);
1536     auto buttonTextLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
1537     CHECK_NULL_VOID(buttonTextLayoutProperty);
1538     Color textColor;
1539     Color::ParseColorString(textColorStr, textColor);
1540     buttonTextLayoutProperty->UpdateContent(dialogProperties_.buttons[btnIndex].text);
1541     buttonTextLayoutProperty->UpdateTextColor(textColor);
1542     buttonTextNode->MarkModifyDone();
1543     buttonTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1544 }
1545 
UpdateButtonsProperty()1546 void DialogPattern::UpdateButtonsProperty()
1547 {
1548     int32_t btnIndex = 0;
1549     if (buttonContainer_) {
1550         isFirstDefaultFocus_ = true;
1551         for (const auto& buttonNode : buttonContainer_->GetChildren()) {
1552             if (buttonNode->GetTag() != V2::BUTTON_ETS_TAG) {
1553                 continue;
1554             }
1555             auto buttonFrameNode = DynamicCast<FrameNode>(buttonNode);
1556             UpdateButtonsPropertyForEachButton(buttonFrameNode, btnIndex);
1557             ++btnIndex;
1558         }
1559     } else {
1560         auto upgradedMenuNode = menuNode_.Upgrade();
1561         CHECK_NULL_VOID(upgradedMenuNode);
1562         for (const auto& rowNode : upgradedMenuNode->GetChildren()) {
1563             if (rowNode->GetTag() != V2::ROW_ETS_TAG) {
1564                 continue;
1565             }
1566             auto buttonFrameNode = DynamicCast<FrameNode>(rowNode->GetFirstChild());
1567             if (buttonFrameNode && buttonFrameNode->GetTag() == V2::BUTTON_ETS_TAG) {
1568                 UpdateButtonsPropertyForEachButton(buttonFrameNode, btnIndex);
1569             }
1570             ++btnIndex;
1571         }
1572     }
1573 }
1574 
UpdatePropertyForElderly(const std::vector<ButtonInfo> & buttons)1575 void DialogPattern::UpdatePropertyForElderly(const std::vector<ButtonInfo>& buttons)
1576 {
1577     isSuitableForElderly_ = false;
1578     notAdapationAging_ = false;
1579     auto host = GetHost();
1580     CHECK_NULL_VOID(host);
1581     auto pipeline = host->GetContextRefPtr();
1582     CHECK_NULL_VOID(pipeline);
1583     auto windowManager = pipeline->GetWindowManager();
1584     CHECK_NULL_VOID(windowManager);
1585     auto dialogContext = GetContext();
1586     CHECK_NULL_VOID(dialogContext);
1587     TAG_LOGI(AceLogTag::ACE_DIALOG, "dialog GetContext fontScale : %{public}f", dialogContext->GetFontScale());
1588     if (GreatOrEqual(dialogContext->GetFontScale(), dialogTheme_->GetMinFontScaleForElderly())) {
1589         if (pipeline->GetRootHeight() < dialogTheme_->GetDialogLandscapeHeightBoundary().ConvertToPx() &&
1590             (windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
1591                 windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) {
1592             notAdapationAging_ = true;
1593             return;
1594         }
1595         deviceOrientation_ = SystemProperties::GetDeviceOrientation();
1596         if (buttons.size() >= THREE_BUTTON_MODE && deviceOrientation_ == DeviceOrientation::LANDSCAPE) {
1597             notAdapationAging_ = true;
1598             return;
1599         }
1600         fontScaleForElderly_ = dialogContext->GetFontScale();
1601         isSuitableForElderly_ = true;
1602         notAdapationAging_ = false;
1603     }
1604 }
1605 
NeedsButtonDirectionChange(const std::vector<ButtonInfo> & buttons)1606 bool DialogPattern::NeedsButtonDirectionChange(const std::vector<ButtonInfo>& buttons)
1607 {
1608     CHECK_NULL_RETURN(buttonContainer_, false);
1609     if (buttons.size() == ONE_BUTTON_MODE || buttonContainer_->GetTag() != V2::ROW_ETS_TAG) {
1610         return false;
1611     }
1612     auto host = GetHost();
1613     CHECK_NULL_RETURN(host, false);
1614     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1615     CHECK_NULL_RETURN(props, false);
1616     auto buttonLayoutConstraint = props->GetLayoutConstraint();
1617     isSuitOldMeasure_ = true;
1618     host->Measure(buttonLayoutConstraint);
1619     isSuitOldMeasure_ = false;
1620     const auto& children = buttonContainer_->GetChildren();
1621     for (const auto& child : children) {
1622         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
1623             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1624             CHECK_NULL_RETURN(buttonNode, false);
1625             auto buttonTextNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
1626             CHECK_NULL_RETURN(buttonTextNode, false);
1627             auto textGeometryNode = buttonTextNode->GetGeometryNode();
1628             CHECK_NULL_RETURN(textGeometryNode, false);
1629             auto textFarmeSize = textGeometryNode->GetFrameSize();
1630             auto textPattern = buttonTextNode->GetPattern<TextPattern>();
1631             CHECK_NULL_RETURN(textPattern, false);
1632             auto textDisplay = UtfUtils::Str16ToStr8(textPattern->GetTextForDisplay());
1633             auto textProps = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
1634             CHECK_NULL_RETURN(textProps, false);
1635             Dimension buttonTextSize = textProps->GetFontSize().value_or(dialogTheme_->GetButtonTextSize());
1636             MeasureContext measureContext;
1637             measureContext.textContent = textDisplay;
1638             measureContext.fontSize = buttonTextSize;
1639             auto dialogContext = GetContext();
1640             CHECK_NULL_RETURN(dialogContext, false);
1641             if (isSuitableForElderly_ && dialogContext->GetFontScale() >= dialogTheme_->GetTitleMaxFontScale() &&
1642                 SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
1643                 measureContext.fontSize =
1644                     Dimension(buttonTextSize.Value() * dialogTheme_->GetTitleMaxFontScale(), DimensionUnit::VP);
1645             }
1646             auto fontweight = StringUtils::FontWeightToString(FontWeight::MEDIUM);
1647             measureContext.fontWeight = fontweight;
1648             Size measureSize = MeasureUtil::MeasureTextSize(measureContext);
1649             if (measureSize.Width() != textFarmeSize.Width()) {
1650                 return true;
1651             }
1652         }
1653     }
1654     return false;
1655 }
1656 
CheckScrollHeightIsNegative(const RefPtr<UINode> & contentColumn,const DialogProperties & Dialogprops)1657 void DialogPattern::CheckScrollHeightIsNegative(
1658     const RefPtr<UINode>& contentColumn, const DialogProperties& Dialogprops)
1659 {
1660     CHECK_NULL_VOID(buttonContainer_);
1661     if (Dialogprops.buttons.size() == ONE_BUTTON_MODE || buttonContainer_->GetTag() == V2::ROW_ETS_TAG) {
1662         return;
1663     }
1664     auto host = GetHost();
1665     CHECK_NULL_VOID(host);
1666     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1667     CHECK_NULL_VOID(props);
1668     auto buttonLayoutConstraint = props->GetLayoutConstraint();
1669     isSuitOldMeasure_ = true;
1670     host->Measure(buttonLayoutConstraint);
1671     isSuitOldMeasure_ = false;
1672     if (isScrollHeightNegative_) {
1673         isSuitableForElderly_ = false;
1674         notAdapationAging_ = true;
1675         contentColumn->RemoveChild(buttonContainer_);
1676         auto buttonContainerNew = BuildButtons(Dialogprops.buttons, Dialogprops.buttonDirection);
1677         buttonContainerNew->MountToParent(contentColumn);
1678         buttonContainer_ = buttonContainerNew;
1679     }
1680 }
1681 
UpdateDeviceOrientation(const DeviceOrientation & deviceOrientation)1682 void DialogPattern::UpdateDeviceOrientation(const DeviceOrientation& deviceOrientation)
1683 {
1684     if (deviceOrientation_ != deviceOrientation) {
1685         CHECK_NULL_VOID(buttonContainer_);
1686         OnFontConfigurationUpdate();
1687         auto host = GetHost();
1688         CHECK_NULL_VOID(host);
1689         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1690         deviceOrientation_ = deviceOrientation;
1691     }
1692 }
1693 
UpdateTitleTextFontScale()1694 void DialogPattern::UpdateTitleTextFontScale()
1695 {
1696     auto host = GetHost();
1697     CHECK_NULL_VOID(host);
1698     auto pipelineContext = host->GetContext();
1699     CHECK_NULL_VOID(pipelineContext);
1700     double maxAppFontScale = pipelineContext->GetMaxAppFontScale();
1701     CHECK_NULL_VOID(titleContainer_);
1702     auto scale = dialogTheme_->GetMinFontScaleForElderly();
1703     if (isSuitableForElderly_) {
1704         scale = dialogTheme_->GetTitleMaxFontScale();
1705     }
1706     if (titleContainer_->GetTag() == V2::COLUMN_ETS_TAG) {
1707         auto children = titleContainer_->GetChildren();
1708         for (const auto& child : children) {
1709             auto textNode = AceType::DynamicCast<FrameNode>(child->GetChildAtIndex(START_CHILD_INDEX));
1710             CHECK_NULL_VOID(textNode);
1711             auto titleProp = AceType::DynamicCast<TextLayoutProperty>(textNode->GetLayoutProperty());
1712             CHECK_NULL_VOID(titleProp);
1713             if (notAdapationAging_) {
1714                 titleProp->UpdateMaxFontScale(std::min<double>(dialogTheme_->GetDialogDefaultScale(), maxAppFontScale));
1715             } else {
1716                 titleProp->UpdateMaxFontScale(std::min<double>(scale, maxAppFontScale));
1717                 titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
1718             }
1719         }
1720     } else {
1721         auto textNode = AceType::DynamicCast<FrameNode>(titleContainer_->GetChildAtIndex(START_CHILD_INDEX));
1722         CHECK_NULL_VOID(textNode);
1723         auto titleProp = AceType::DynamicCast<TextLayoutProperty>(textNode->GetLayoutProperty());
1724         CHECK_NULL_VOID(titleProp);
1725         if (notAdapationAging_) {
1726             titleProp->UpdateMaxFontScale(std::min<double>(dialogTheme_->GetDialogDefaultScale(), maxAppFontScale));
1727         } else {
1728             titleProp->UpdateMaxFontScale(std::min<double>(scale, maxAppFontScale));
1729             titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
1730         }
1731     }
1732 }
1733 
UpdateTextFontScale()1734 void DialogPattern::UpdateTextFontScale()
1735 {
1736     UpdateTitleTextFontScale();
1737     CHECK_NULL_VOID(contentNodeMap_[DialogContentNode::MESSAGE]);
1738     auto scale = dialogTheme_->GetMinFontScaleForElderly();
1739     auto contentProp =
1740         AceType::DynamicCast<TextLayoutProperty>(contentNodeMap_[DialogContentNode::MESSAGE]->GetLayoutProperty());
1741     auto context = GetContext();
1742     CHECK_NULL_VOID(context);
1743     double maxAppFontScale = context->GetMaxAppFontScale();
1744     CHECK_NULL_VOID(contentProp);
1745     if (isSuitableForElderly_) {
1746         scale = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE
1747                     ? dialogTheme_->GetContentLandscapeMaxFontScale()
1748                     : dialogTheme_->GetContentMaxFontScale();
1749     }
1750     if (notAdapationAging_) {
1751         contentProp->UpdateMaxFontScale(std::min<double>(dialogTheme_->GetDialogDefaultScale(), maxAppFontScale));
1752     } else {
1753         contentProp->UpdateMaxFontScale(std::min<double>(scale, maxAppFontScale));
1754     }
1755     CHECK_NULL_VOID(buttonContainer_);
1756     MarginProperty margin;
1757     if (isSuitableForElderly_) {
1758         scale = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE
1759                     ? dialogTheme_->GetButtonLandscapeMaxFontScale()
1760                     : dialogTheme_->GetButtonMaxFontScale();
1761         margin.top = CalcLength(8.0_vp);
1762         margin.bottom = CalcLength(8.0_vp);
1763     }
1764     const auto& children = buttonContainer_->GetChildren();
1765     for (const auto& child : children) {
1766         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
1767             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1768             CHECK_NULL_VOID(buttonNode);
1769             auto buttonTextNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
1770             CHECK_NULL_VOID(buttonTextNode);
1771             auto textProp = AceType::DynamicCast<TextLayoutProperty>(buttonTextNode->GetLayoutProperty());
1772             CHECK_NULL_VOID(textProp);
1773             if (notAdapationAging_) {
1774                 textProp->UpdateMaxFontScale(std::min<double>(dialogTheme_->GetDialogDefaultScale(), maxAppFontScale));
1775             } else {
1776                 textProp->UpdateMaxFontScale(std::min<double>(scale, maxAppFontScale));
1777             }
1778             if (isSuitableForElderly_) {
1779                 textProp->UpdateMargin(margin);
1780             }
1781         }
1782     }
1783 }
1784 
UpdateFontScale()1785 void DialogPattern::UpdateFontScale()
1786 {
1787     auto dialogContext = GetContext();
1788     CHECK_NULL_VOID(dialogContext);
1789     if (dialogContext->GetFontScale() != fontScaleForElderly_) {
1790         OnFontConfigurationUpdate();
1791         auto host = GetHost();
1792         CHECK_NULL_VOID(host);
1793         host->MarkModifyDone();
1794         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1795         fontScaleForElderly_ = dialogContext->GetFontScale();
1796     }
1797 }
1798 
SetButtonEnabled(const RefPtr<FrameNode> & buttonNode,bool enabled)1799 void DialogPattern::SetButtonEnabled(const RefPtr<FrameNode>& buttonNode, bool enabled)
1800 {
1801     // set Enabled and Focusable
1802     auto buttonButtonEvent = buttonNode->GetOrCreateEventHub<ButtonEventHub>();
1803     CHECK_NULL_VOID(buttonButtonEvent);
1804     buttonButtonEvent->SetEnabled(enabled);
1805     buttonNode->GetOrCreateFocusHub()->SetFocusable(enabled);
1806 }
1807 
UpdateWrapperBackgroundStyle(const RefPtr<FrameNode> & host,const RefPtr<DialogTheme> & dialogTheme)1808 void DialogPattern::UpdateWrapperBackgroundStyle(const RefPtr<FrameNode>& host, const RefPtr<DialogTheme>& dialogTheme)
1809 {
1810     auto col = DynamicCast<FrameNode>(host->GetChildAtIndex(START_CHILD_INDEX));
1811     CHECK_NULL_VOID(col);
1812     auto colRenderContext = col->GetRenderContext();
1813     CHECK_NULL_VOID(colRenderContext);
1814     if (!dialogProperties_.customStyle && !dialogProperties_.backgroundColor.has_value() &&
1815         (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) || !colRenderContext->IsUniRenderEnabled() ||
1816             !dialogProperties_.isSysBlurStyle)) {
1817         colRenderContext->UpdateBackgroundColor(dialogTheme->GetBackgroundColor());
1818     }
1819     if (colRenderContext->GetBackBlurStyle().has_value()) {
1820         colRenderContext->UpdateBackBlurStyle(colRenderContext->GetBackBlurStyle());
1821     }
1822 }
1823 
DumpInfo()1824 void DialogPattern::DumpInfo()
1825 {
1826     DumpLog::GetInstance().AddDesc("Type: " + DialogTypeUtils::ConvertDialogTypeToString(dialogProperties_.type));
1827     if (!dialogProperties_.title.empty()) {
1828         DumpLog::GetInstance().AddDesc("Title: " + dialogProperties_.title);
1829     }
1830     if (!dialogProperties_.subtitle.empty()) {
1831         DumpLog::GetInstance().AddDesc("Subtitle: " + dialogProperties_.subtitle);
1832     }
1833     if (!dialogProperties_.content.empty()) {
1834         DumpLog::GetInstance().AddDesc("Content: " + dialogProperties_.content);
1835     }
1836     DumpLog::GetInstance().AddDesc(
1837         "DialogButtonDirection: " +
1838         DialogButtonDirectionUtils::ConvertDialogButtonDirectionToString(dialogProperties_.buttonDirection));
1839     if (dialogProperties_.width.has_value()) {
1840         DumpLog::GetInstance().AddDesc("Width: " + dialogProperties_.width.value().ToString());
1841     }
1842     if (dialogProperties_.height.has_value()) {
1843         DumpLog::GetInstance().AddDesc("Height: " + dialogProperties_.height.value().ToString());
1844     }
1845     if (dialogProperties_.backgroundBlurStyle.has_value()) {
1846         DumpLog::GetInstance().AddDesc(
1847             "BackgroundBlurStyle: " + std::to_string(dialogProperties_.backgroundBlurStyle.value()));
1848     }
1849     if (dialogProperties_.borderWidth.has_value()) {
1850         DumpLog::GetInstance().AddDesc("BorderWidth: " + dialogProperties_.borderWidth.value().ToString());
1851     }
1852     if (dialogProperties_.borderColor.has_value()) {
1853         DumpLog::GetInstance().AddDesc("BorderColor: " + dialogProperties_.borderColor.value().ToString());
1854     }
1855     if (dialogProperties_.backgroundColor.has_value()) {
1856         DumpLog::GetInstance().AddDesc("BackgroundColor: " + dialogProperties_.backgroundColor.value().ToString());
1857     }
1858     if (dialogProperties_.borderRadius.has_value()) {
1859         DumpLog::GetInstance().AddDesc("BorderRadius: " + dialogProperties_.borderRadius.value().ToString());
1860     }
1861     DumpBoolProperty();
1862     DumpObjectProperty();
1863 }
1864 
DumpBoolProperty()1865 void DialogPattern::DumpBoolProperty()
1866 {
1867     DumpLog::GetInstance().AddDesc("AutoCancel: " + GetBoolStr(dialogProperties_.autoCancel));
1868     DumpLog::GetInstance().AddDesc("CustomStyle: " + GetBoolStr(dialogProperties_.customStyle));
1869     DumpLog::GetInstance().AddDesc("IsMenu: " + GetBoolStr(dialogProperties_.isMenu));
1870     DumpLog::GetInstance().AddDesc("IsMask: " + GetBoolStr(dialogProperties_.isMask));
1871     DumpLog::GetInstance().AddDesc("IsModal: " + GetBoolStr(dialogProperties_.isModal));
1872     DumpLog::GetInstance().AddDesc("IsSceneBoardDialog: " + GetBoolStr(dialogProperties_.isSceneBoardDialog));
1873     DumpLog::GetInstance().AddDesc("IsSysBlurStyle: " + GetBoolStr(dialogProperties_.isSysBlurStyle));
1874     DumpLog::GetInstance().AddDesc("IsShowInSubWindow: " + GetBoolStr(dialogProperties_.isShowInSubWindow));
1875 }
1876 
DumpObjectProperty()1877 void DialogPattern::DumpObjectProperty()
1878 {
1879     DumpLog::GetInstance().AddDesc(
1880         "Alignment: " + DialogAlignmentUtils::ConvertDialogAlignmentToString(dialogProperties_.alignment));
1881     DumpLog::GetInstance().AddDesc("Offset: { dx: " + dialogProperties_.offset.GetX().ToString() +
1882                                    " dy: " + dialogProperties_.offset.GetY().ToString() + " }");
1883     if (dialogProperties_.buttons.size() > 0) {
1884         std::stringstream butonInfoSteam;
1885         butonInfoSteam << "Buttons: [";
1886         for (auto buttonInfo : dialogProperties_.buttons) {
1887             butonInfoSteam << "{ text: " << buttonInfo.text << " , color: " << buttonInfo.textColor << " }, ";
1888         }
1889         butonInfoSteam << "]";
1890         DumpLog::GetInstance().AddDesc(butonInfoSteam.str());
1891     }
1892     if (dialogProperties_.shadow.has_value()) {
1893         auto shadow = dialogProperties_.shadow.value();
1894         std::stringstream butonInfoSteam;
1895         static const int32_t precision = 2;
1896         butonInfoSteam << "Shadow: {";
1897         butonInfoSteam << " radius:" << std::fixed << std::setprecision(precision) << shadow.GetBlurRadius();
1898         butonInfoSteam << " style:" << std::to_string(static_cast<int32_t>(shadow.GetStyle()));
1899         butonInfoSteam << " type:" << std::to_string(static_cast<int32_t>(shadow.GetShadowType()));
1900         butonInfoSteam << " fill:" << GetBoolStr(shadow.GetIsFilled());
1901         butonInfoSteam << " offset:" << shadow.GetOffset().ToString();
1902         butonInfoSteam << " }";
1903         DumpLog::GetInstance().AddDesc(butonInfoSteam.str());
1904     }
1905     if (dialogProperties_.maskColor.has_value()) {
1906         DumpLog::GetInstance().AddDesc("MaskColor: " + dialogProperties_.maskColor.value().ToString());
1907     }
1908     if (dialogProperties_.maskRect.has_value()) {
1909         DumpLog::GetInstance().AddDesc("MaskRect: " + dialogProperties_.maskRect.value().ToString());
1910     }
1911 }
1912 
NeedUpdateHostWindowRect()1913 bool DialogPattern::NeedUpdateHostWindowRect()
1914 {
1915     CHECK_NULL_RETURN(isUIExtensionSubWindow_, false);
1916     if (!SystemProperties::IsSuperFoldDisplayDevice()) {
1917         return false;
1918     }
1919 
1920     auto host = GetHost();
1921     CHECK_NULL_RETURN(host, false);
1922     auto pipeline = host->GetContextRefPtr();
1923     CHECK_NULL_RETURN(pipeline, false);
1924     auto currentId = pipeline->GetInstanceId();
1925     if (currentId < MIN_SUBCONTAINER_ID) {
1926         return false;
1927     }
1928 
1929     auto container = AceEngine::Get().GetContainer(currentId);
1930     CHECK_NULL_RETURN(container, false);
1931     if (container->GetCurrentFoldStatus() == FoldStatus::HALF_FOLD) {
1932         auto subwindow = SubwindowManager::GetInstance()->GetSubwindowById(currentId);
1933         CHECK_NULL_RETURN(subwindow, false);
1934         return subwindow->IsSameDisplayWithParentWindow();
1935     }
1936 
1937     return false;
1938 }
1939 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1940 void DialogPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1941 {
1942     auto forceUpdate = NeedUpdateHostWindowRect();
1943     auto isWindowChanged = type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::RESIZE;
1944 
1945     TAG_LOGI(AceLogTag::ACE_DIALOG,
1946         "WindowSize is changed, type: %{public}d isFoldStatusChanged_: %{public}d forceUpdate: %{public}d", type,
1947         isFoldStatusChanged_, forceUpdate);
1948 
1949     if (isFoldStatusChanged_ || isWindowChanged || forceUpdate) {
1950         auto host = GetHost();
1951         CHECK_NULL_VOID(host);
1952         InitHostWindowRect();
1953         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1954         isFoldStatusChanged_ = false;
1955     }
1956 }
1957 
UpdateHostWindowRect()1958 void DialogPattern::UpdateHostWindowRect()
1959 {
1960     CHECK_NULL_VOID(isUIExtensionSubWindow_);
1961 
1962     auto host = GetHost();
1963     CHECK_NULL_VOID(host);
1964     auto pipeline = host->GetContextRefPtr();
1965     CHECK_NULL_VOID(pipeline);
1966     auto currentId = pipeline->GetInstanceId();
1967     if (currentId < MIN_SUBCONTAINER_ID) {
1968         return;
1969     }
1970 
1971     auto needUpdate = true;
1972     if (SystemProperties::IsSuperFoldDisplayDevice()) {
1973         auto container = AceEngine::Get().GetContainer(currentId);
1974         auto isHalfFold = container && container->GetCurrentFoldStatus() == FoldStatus::HALF_FOLD;
1975         auto subwindow = SubwindowManager::GetInstance()->GetSubwindowById(currentId);
1976         needUpdate = isHalfFold && subwindow && subwindow->IsSameDisplayWithParentWindow() && dialogProperties_.isModal;
1977     }
1978 
1979     if (needUpdate) {
1980         InitHostWindowRect();
1981         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1982     }
1983 }
1984 
InitHostWindowRect()1985 void DialogPattern::InitHostWindowRect()
1986 {
1987     if (!dialogProperties_.isShowInSubWindow) {
1988         isUIExtensionSubWindow_ = false;
1989         hostWindowRect_.Reset();
1990         return;
1991     }
1992 
1993     auto currentId = Container::CurrentId();
1994     auto container = Container::Current();
1995     CHECK_NULL_VOID(container);
1996     if (container->IsSubContainer()) {
1997         auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
1998         container = AceEngine::Get().GetContainer(parentContainerId);
1999         CHECK_NULL_VOID(container);
2000     }
2001 
2002     if (container->IsUIExtensionWindow()) {
2003         isUIExtensionSubWindow_ = true;
2004         auto host = GetHost();
2005         CHECK_NULL_VOID(host);
2006         auto pipeline = host->GetContextRefPtr();
2007         CHECK_NULL_VOID(pipeline);
2008         auto subContainerId = pipeline->GetInstanceId();
2009         auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(subContainerId, SubwindowType::TYPE_DIALOG);
2010         CHECK_NULL_VOID(subwindow);
2011         auto rect = subwindow->GetUIExtensionHostWindowRect();
2012         hostWindowRect_ = RectF(rect.Left(), rect.Top(), rect.Width(), rect.Height());
2013     }
2014     TAG_LOGI(AceLogTag::ACE_DIALOG, "InitHostWindowRect: %{public}s", hostWindowRect_.ToString().c_str());
2015 }
2016 
DumpInfo(std::unique_ptr<JsonValue> & json)2017 void DialogPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
2018 {
2019     json->Put("Type", DialogTypeUtils::ConvertDialogTypeToString(dialogProperties_.type).c_str());
2020     if (!dialogProperties_.title.empty()) {
2021         json->Put("Title", dialogProperties_.title.c_str());
2022     }
2023     if (!dialogProperties_.subtitle.empty()) {
2024         json->Put("Subtitle", dialogProperties_.subtitle.c_str());
2025     }
2026     if (!dialogProperties_.content.empty()) {
2027         json->Put("Content", dialogProperties_.content.c_str());
2028     }
2029     json->Put("DialogButtonDirection",
2030         DialogButtonDirectionUtils::ConvertDialogButtonDirectionToString(dialogProperties_.buttonDirection).c_str());
2031     if (dialogProperties_.width.has_value()) {
2032         json->Put("Width", dialogProperties_.width.value().ToString().c_str());
2033     }
2034     if (dialogProperties_.height.has_value()) {
2035         json->Put("Height", dialogProperties_.height.value().ToString().c_str());
2036     }
2037     if (dialogProperties_.backgroundBlurStyle.has_value()) {
2038         json->Put("BackgroundBlurStyle", std::to_string(dialogProperties_.backgroundBlurStyle.value()).c_str());
2039     }
2040     if (dialogProperties_.borderWidth.has_value()) {
2041         json->Put("BorderWidth", dialogProperties_.borderWidth.value().ToString().c_str());
2042     }
2043     if (dialogProperties_.borderColor.has_value()) {
2044         json->Put("BorderColor", dialogProperties_.borderColor.value().ToString().c_str());
2045     }
2046     if (dialogProperties_.backgroundColor.has_value()) {
2047         json->Put("BackgroundColor", dialogProperties_.backgroundColor.value().ToString().c_str());
2048     }
2049     if (dialogProperties_.borderRadius.has_value()) {
2050         json->Put("BorderRadius", dialogProperties_.borderRadius.value().ToString().c_str());
2051     }
2052     DumpBoolProperty(json);
2053     DumpObjectProperty(json);
2054 }
2055 
DumpBoolProperty(std::unique_ptr<JsonValue> & json)2056 void DialogPattern::DumpBoolProperty(std::unique_ptr<JsonValue>& json)
2057 {
2058     json->Put("AutoCancel", GetBoolStr(dialogProperties_.autoCancel).c_str());
2059     json->Put("CustomStyle", GetBoolStr(dialogProperties_.customStyle).c_str());
2060     json->Put("IsMenu", GetBoolStr(dialogProperties_.isMenu).c_str());
2061     json->Put("IsMask", GetBoolStr(dialogProperties_.isMask).c_str());
2062     json->Put("IsModal", GetBoolStr(dialogProperties_.isModal).c_str());
2063     json->Put("IsSceneBoardDialog", GetBoolStr(dialogProperties_.isSceneBoardDialog).c_str());
2064     json->Put("IsSysBlurStyle", GetBoolStr(dialogProperties_.isSysBlurStyle).c_str());
2065     json->Put("IsShowInSubWindow", GetBoolStr(dialogProperties_.isShowInSubWindow).c_str());
2066 }
2067 
DumpObjectProperty(std::unique_ptr<JsonValue> & json)2068 void DialogPattern::DumpObjectProperty(std::unique_ptr<JsonValue>& json)
2069 {
2070     json->Put("Alignment", DialogAlignmentUtils::ConvertDialogAlignmentToString(dialogProperties_.alignment).c_str());
2071     std::unique_ptr<JsonValue> children = JsonUtil::Create(true);
2072     children->Put("dx", dialogProperties_.offset.GetX().ToString().c_str());
2073     children->Put("dy", dialogProperties_.offset.GetY().ToString().c_str());
2074     json->Put("Offset", children);
2075     if (dialogProperties_.buttons.size() > 0) {
2076         std::unique_ptr<JsonValue> buttons = JsonUtil::Create(true);
2077         int32_t inx = -1;
2078         for (auto buttonInfo : dialogProperties_.buttons) {
2079             std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
2080             child->Put("text", buttonInfo.text.c_str());
2081             child->Put("color", buttonInfo.textColor.c_str());
2082             inx++;
2083             std::string key = "button_" + std::to_string(inx);
2084             buttons->Put(key.c_str(), child);
2085         }
2086         json->Put("buttons", buttons);
2087     }
2088     if (dialogProperties_.shadow.has_value()) {
2089         auto shadow = dialogProperties_.shadow.value();
2090         std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
2091 
2092         child->Put("radius", shadow.GetBlurRadius());
2093         child->Put("style", static_cast<int32_t>(shadow.GetStyle()));
2094         child->Put("type", static_cast<int32_t>(shadow.GetShadowType()));
2095         child->Put("fill", GetBoolStr(shadow.GetIsFilled()).c_str());
2096         child->Put("offset", shadow.GetOffset().ToString().c_str());
2097         json->Put("shadow", child);
2098     }
2099     if (dialogProperties_.maskColor.has_value()) {
2100         json->Put("MaskColor", dialogProperties_.maskColor.value().ToString().c_str());
2101     }
2102     if (dialogProperties_.maskRect.has_value()) {
2103         json->Put("MaskRect", dialogProperties_.maskRect.value().ToString().c_str());
2104     }
2105 }
2106 
IsShowInFreeMultiWindow()2107 bool DialogPattern::IsShowInFreeMultiWindow()
2108 {
2109     auto currentId = Container::CurrentId();
2110     auto container = Container::Current();
2111     if (!container) {
2112         TAG_LOGW(AceLogTag::ACE_DIALOG, "container is null");
2113         return false;
2114     }
2115     if (container->IsSubContainer()) {
2116         currentId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
2117         container = AceEngine::Get().GetContainer(currentId);
2118         if (!container) {
2119             TAG_LOGW(AceLogTag::ACE_DIALOG, "parent container is null");
2120             return false;
2121         }
2122     }
2123     return container->IsFreeMultiWindow();
2124 }
2125 
IsShowInFloatingWindow()2126 bool DialogPattern::IsShowInFloatingWindow()
2127 {
2128     auto currentId = Container::CurrentId();
2129     auto container = Container::Current();
2130     if (!container) {
2131         TAG_LOGW(AceLogTag::ACE_DIALOG, "container is null");
2132         return false;
2133     }
2134     if (container->IsSubContainer()) {
2135         currentId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
2136         container = AceEngine::Get().GetContainer(currentId);
2137         if (!container) {
2138             TAG_LOGW(AceLogTag::ACE_DIALOG, "parent container is null");
2139             return false;
2140         }
2141     }
2142     return container->IsFloatingWindow();
2143 }
2144 
DumpSimplifyBorderProperty(std::unique_ptr<JsonValue> & json)2145 void DialogPattern::DumpSimplifyBorderProperty(std::unique_ptr<JsonValue>& json)
2146 {
2147     if (dialogProperties_.borderWidth.has_value()) {
2148         auto border = dialogProperties_.borderWidth.value();
2149         DimensionUnit unit = border.leftDimen.value_or(
2150             border.topDimen.value_or(border.rightDimen.value_or(border.bottomDimen.value_or(Dimension())))).Unit();
2151         Dimension defaultValue(0, unit);
2152         BorderWidthProperty defaultBorder = { defaultValue, defaultValue, defaultValue, defaultValue, std::nullopt,
2153             std::nullopt };
2154         if (!(border == defaultBorder)) {
2155             json->Put("BorderWidth", border.ToString().c_str());
2156         }
2157     }
2158     if (dialogProperties_.borderColor.has_value()) {
2159         auto color = dialogProperties_.borderColor.value();
2160         BorderColorProperty defaultValue = { Color::BLACK, Color::BLACK, Color::BLACK, Color::BLACK, std::nullopt,
2161             std::nullopt };
2162         if (!(color == defaultValue)) {
2163             json->Put("BorderColor", color.ToString().c_str());
2164         }
2165     }
2166     if (dialogProperties_.borderRadius.has_value()) {
2167         auto radius = dialogProperties_.borderRadius.value();
2168         DimensionUnit unit = radius.radiusTopLeft.value_or(radius.radiusTopRight.value_or(
2169             radius.radiusTopLeft.value_or(radius.radiusBottomLeft.value_or(
2170                 radius.radiusBottomRight.value_or(radius.radiusTopStart.value_or(radius.radiusTopEnd.value_or(
2171                     radius.radiusBottomStart.value_or(radius.radiusBottomEnd.value_or(Dimension()))))))))).Unit();
2172         Dimension defaultValue(0, unit);
2173         BorderRadiusProperty defaultRadius(defaultValue);
2174         if (!(radius == defaultRadius)) {
2175             json->Put("BorderRadius", dialogProperties_.borderRadius.value().ToString().c_str());
2176         }
2177     }
2178 }
2179 
DumpSimplifySizeProperty(std::unique_ptr<JsonValue> & json)2180 void DialogPattern::DumpSimplifySizeProperty(std::unique_ptr<JsonValue>& json)
2181 {
2182     if (dialogProperties_.width.has_value() || dialogProperties_.height.has_value()) {
2183         DimensionUnit unit = dialogProperties_.width.has_value() ?
2184             dialogProperties_.width.value().Unit() : dialogProperties_.height.value().Unit();
2185         CalcDimension defaultCalcDimen(0, unit);
2186         if (dialogProperties_.width.value_or(defaultCalcDimen) != defaultCalcDimen &&
2187             dialogProperties_.height.value_or(defaultCalcDimen) != defaultCalcDimen) {
2188             json->Put("Width", dialogProperties_.width.value_or(defaultCalcDimen).ToString().c_str());
2189             json->Put("Height", dialogProperties_.height.value_or(defaultCalcDimen).ToString().c_str());
2190         }
2191     }
2192 }
2193 
DumpSimplifyBoolProperty(std::unique_ptr<JsonValue> & json)2194 void DialogPattern::DumpSimplifyBoolProperty(std::unique_ptr<JsonValue>& json)
2195 {
2196     if (dialogProperties_.autoCancel) {
2197         json->Put("AutoCancel", GetBoolStr(dialogProperties_.autoCancel).c_str());
2198     }
2199     if (dialogProperties_.customStyle) {
2200         json->Put("CustomStyle", GetBoolStr(dialogProperties_.customStyle).c_str());
2201     }
2202     if (dialogProperties_.isMenu) {
2203         json->Put("IsMenu", GetBoolStr(dialogProperties_.isMenu).c_str());
2204     }
2205     if (dialogProperties_.isMask) {
2206         json->Put("IsMask", GetBoolStr(dialogProperties_.isMask).c_str());
2207     }
2208     if (dialogProperties_.isModal) {
2209         json->Put("IsModal", GetBoolStr(dialogProperties_.isModal).c_str());
2210     }
2211     if (dialogProperties_.isSceneBoardDialog) {
2212         json->Put("IsSceneBoardDialog", GetBoolStr(dialogProperties_.isSceneBoardDialog).c_str());
2213     }
2214     if (dialogProperties_.isSysBlurStyle) {
2215         json->Put("IsSysBlurStyle", GetBoolStr(dialogProperties_.isSysBlurStyle).c_str());
2216     }
2217     if (dialogProperties_.isShowInSubWindow) {
2218         json->Put("IsShowInSubWindow", GetBoolStr(dialogProperties_.isShowInSubWindow).c_str());
2219     }
2220 }
2221 
DumpSimplifyObjectProperty(std::unique_ptr<JsonValue> & json)2222 void DialogPattern::DumpSimplifyObjectProperty(std::unique_ptr<JsonValue>& json)
2223 {
2224     json->Put("Alignment", DialogAlignmentUtils::ConvertDialogAlignmentToString(dialogProperties_.alignment).c_str());
2225     std::stringstream stream;
2226     stream << dialogProperties_.offset.GetX().ToString() << "," << dialogProperties_.offset.GetY().ToString();
2227     json->Put("Offset", stream.str().c_str());
2228     if (!dialogProperties_.buttons.empty()) {
2229         std::unique_ptr<JsonValue> buttons = JsonUtil::Create(true);
2230         int32_t index = -1;
2231         for (const auto& buttonInfo : dialogProperties_.buttons) {
2232             std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
2233             child->Put("Text", buttonInfo.text.c_str());
2234             child->Put("Color", buttonInfo.textColor.c_str());
2235             index++;
2236             std::string key = "Button" + std::to_string(index);
2237             buttons->PutRef(key.c_str(), std::move(child));
2238         }
2239         json->PutRef("Buttons", std::move(buttons));
2240     }
2241     if (dialogProperties_.shadow.has_value()) {
2242         auto shadow = dialogProperties_.shadow.value();
2243         std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
2244 
2245         child->Put("Radius", shadow.GetBlurRadius());
2246         child->Put("Style", static_cast<int32_t>(shadow.GetStyle()));
2247         child->Put("Type", static_cast<int32_t>(shadow.GetShadowType()));
2248         child->Put("Fill", GetBoolStr(shadow.GetIsFilled()).c_str());
2249         child->Put("Offset", shadow.GetOffset().ToString().c_str());
2250         json->PutRef("Shadow", std::move(child));
2251     }
2252     if (dialogProperties_.maskColor.has_value()) {
2253         json->Put("MaskColor", dialogProperties_.maskColor.value().ToString().c_str());
2254     }
2255     if (dialogProperties_.maskRect.has_value()) {
2256         json->Put("MaskRect", dialogProperties_.maskRect.value().ToString().c_str());
2257     }
2258 }
2259 
GetEmbeddedOverlay(const RefPtr<OverlayManager> & context)2260 RefPtr<OverlayManager> DialogPattern::GetEmbeddedOverlay(const RefPtr<OverlayManager>& context)
2261 {
2262     auto host = GetHost();
2263     auto overlayManager = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(host);
2264     CHECK_NULL_RETURN(overlayManager, context);
2265     return overlayManager;
2266 }
2267 
OnAttachToMainTree()2268 void DialogPattern::OnAttachToMainTree()
2269 {
2270     AddFollowParentWindowLayoutNode();
2271     auto host = GetHost();
2272     CHECK_NULL_VOID(host);
2273     auto parentNode = AceType::DynamicCast<FrameNode>(host->GetParent());
2274     CHECK_NULL_VOID(parentNode);
2275     if (parentNode->GetTag() != V2::NAVDESTINATION_VIEW_ETS_TAG) {
2276         return;
2277     }
2278     auto dialogRenderContext = host->GetRenderContext();
2279     CHECK_NULL_VOID(dialogRenderContext);
2280     auto navDestinationPattern = parentNode->GetPattern<NavDestinationPattern>();
2281     CHECK_NULL_VOID(navDestinationPattern);
2282     auto zIndex = navDestinationPattern->GetTitlebarZIndex();
2283     dialogRenderContext->UpdateZIndex(zIndex + 1);
2284 }
2285 
OnDetachFromMainTree()2286 void DialogPattern::OnDetachFromMainTree()
2287 {
2288     RemoveFollowParentWindowLayoutNode();
2289     auto host = GetHost();
2290     CHECK_NULL_VOID(host);
2291     auto context = host->GetContext();
2292     CHECK_NULL_VOID(context);
2293     auto overlay = context->GetOverlayManager();
2294     CHECK_NULL_VOID(overlay);
2295     overlay->RemoveDialogFromMapForcefully(host);
2296 }
2297 
GetOverlayManager(const RefPtr<FrameNode> & host)2298 RefPtr<OverlayManager> DialogPattern::GetOverlayManager(const RefPtr<FrameNode>& host)
2299 {
2300     RefPtr<PipelineContext> pipeline;
2301     if (host) {
2302         pipeline = host->GetContext();
2303     } else {
2304         auto node = GetHost();
2305         CHECK_NULL_RETURN(node, nullptr);
2306         pipeline = node->GetContextRefPtr();
2307     }
2308     CHECK_NULL_RETURN(pipeline, nullptr);
2309     auto overlayManager = pipeline->GetOverlayManager();
2310     CHECK_NULL_RETURN(overlayManager, nullptr);
2311     return GetEmbeddedOverlay(overlayManager);
2312 }
2313 
OverlayDismissDialog(const RefPtr<FrameNode> & dialogNode)2314 void DialogPattern::OverlayDismissDialog(const RefPtr<FrameNode>& dialogNode)
2315 {
2316     auto overlayManager = GetOverlayManager(nullptr);
2317     CHECK_NULL_VOID(overlayManager);
2318     overlayManager->RemoveDialog(dialogNode, false);
2319     if (overlayManager->isMaskNode(GetHost()->GetId())) {
2320         overlayManager->PopModalDialog(GetHost()->GetId());
2321     }
2322 }
2323 
AddFollowParentWindowLayoutNode()2324 void DialogPattern::AddFollowParentWindowLayoutNode()
2325 {
2326     auto host = GetHost();
2327     CHECK_NULL_VOID(host);
2328     auto pipeline = host->GetContextRefPtr();
2329     CHECK_NULL_VOID(pipeline);
2330     auto containerId = pipeline->GetInstanceId();
2331     auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(containerId, SubwindowType::TYPE_DIALOG);
2332     CHECK_NULL_VOID(subwindow);
2333     subwindow->AddFollowParentWindowLayoutNode(host->GetId());
2334 }
2335 
RemoveFollowParentWindowLayoutNode()2336 void DialogPattern::RemoveFollowParentWindowLayoutNode()
2337 {
2338     auto host = GetHost();
2339     CHECK_NULL_VOID(host);
2340     auto pipeline = host->GetContextRefPtr();
2341     CHECK_NULL_VOID(pipeline);
2342     auto containerId = pipeline->GetInstanceId();
2343     auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(containerId, SubwindowType::TYPE_DIALOG);
2344     CHECK_NULL_VOID(subwindow);
2345     subwindow->RemoveFollowParentWindowLayoutNode(host->GetId());
2346 }
2347 
GetWindowButtonRect(NG::RectF & floatButtons)2348 bool DialogPattern::GetWindowButtonRect(NG::RectF& floatButtons)
2349 {
2350     auto host = GetHost();
2351     CHECK_NULL_RETURN(host, false);
2352     auto pipelineContext = host->GetContext();
2353     CHECK_NULL_RETURN(pipelineContext, false);
2354     auto avoidInfoMgr = pipelineContext->GetAvoidInfoManager();
2355     CHECK_NULL_RETURN(avoidInfoMgr, false);
2356     NG::RectF floatContainerModal;
2357     if (avoidInfoMgr->NeedAvoidContainerModal() &&
2358         avoidInfoMgr->GetContainerModalButtonsRect(floatContainerModal, floatButtons)) {
2359         TAG_LOGD(AceLogTag::ACE_DIALOG, "When hidden, floatButtons rect is %{public}s",
2360             floatButtons.ToString().c_str());
2361         return true;
2362     };
2363     TAG_LOGD(AceLogTag::ACE_DIALOG, "Window title builder shown");
2364     return false;
2365 }
2366 
OnAvoidInfoChange(const ContainerModalAvoidInfo & info)2367 void DialogPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
2368 {
2369     auto host = GetHost();
2370     CHECK_NULL_VOID(host);
2371     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2372 }
2373 
RegisterAvoidInfoChangeListener(const RefPtr<FrameNode> & hostNode)2374 void DialogPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
2375 {
2376     CHECK_NULL_VOID(hostNode);
2377     auto pipeline = hostNode->GetContext();
2378     CHECK_NULL_VOID(pipeline);
2379     auto mgr = pipeline->GetAvoidInfoManager();
2380     CHECK_NULL_VOID(mgr);
2381     mgr->AddAvoidInfoListener(WeakClaim(this));
2382 }
2383 
UnRegisterAvoidInfoChangeListener(FrameNode * hostNode)2384 void DialogPattern::UnRegisterAvoidInfoChangeListener(FrameNode* hostNode)
2385 {
2386     CHECK_NULL_VOID(hostNode);
2387     auto pipeline = hostNode->GetContext();
2388     CHECK_NULL_VOID(pipeline);
2389     auto mgr = pipeline->GetAvoidInfoManager();
2390     CHECK_NULL_VOID(mgr);
2391     mgr->RemoveAvoidInfoListener(WeakClaim(this));
2392 }
2393 
CreateLayoutAlgorithm()2394 RefPtr<LayoutAlgorithm> DialogPattern::CreateLayoutAlgorithm()
2395 {
2396     auto context = GetContext();
2397     return context == nullptr ? AceType::MakeRefPtr<DialogLayoutAlgorithm>()
2398                               : AceType::MakeRefPtr<DialogLayoutAlgorithm>(WeakClaim(context));
2399 }
2400 } // namespace OHOS::Ace::NG
2401