• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
16 
17 #include <climits>
18 #include <cstdint>
19 #include <cstring>
20 #include <optional>
21 #include <string>
22 
23 #include "base/geometry/dimension.h"
24 #include "base/json/json_util.h"
25 #include "base/log/dump_log.h"
26 #include "base/log/log.h"
27 #include "base/memory/ace_type.h"
28 #include "base/memory/referenced.h"
29 #include "base/subwindow/subwindow_manager.h"
30 #include "base/utils/utils.h"
31 #include "bridge/common/dom/dom_type.h"
32 #include "core/common/ace_engine.h"
33 #include "core/common/container.h"
34 #include "core/common/recorder/event_recorder.h"
35 #include "core/components/button/button_theme.h"
36 #include "core/components/common/properties/alignment.h"
37 #include "core/components/theme/icon_theme.h"
38 #include "core/components_ng/base/frame_node.h"
39 #include "core/components_ng/base/inspector_filter.h"
40 #include "core/components_ng/base/ui_node.h"
41 #include "core/components_ng/base/view_stack_processor.h"
42 #include "core/components_ng/event/gesture_event_hub.h"
43 #include "core/components_ng/layout/layout_property.h"
44 #include "core/components_ng/pattern/button/button_layout_property.h"
45 #include "core/components_ng/pattern/button/button_pattern.h"
46 #include "core/components_ng/pattern/divider/divider_layout_property.h"
47 #include "core/components_ng/pattern/divider/divider_model_ng.h"
48 #include "core/components_ng/pattern/divider/divider_pattern.h"
49 #include "core/components_ng/pattern/flex/flex_layout_algorithm.h"
50 #include "core/components_ng/pattern/flex/flex_layout_property.h"
51 #include "core/components_ng/pattern/image/image_pattern.h"
52 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
53 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
54 #include "core/components_ng/pattern/list/list_pattern.h"
55 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
56 #include "core/components_ng/pattern/overlay/dialog_manager.h"
57 #include "core/components_ng/pattern/overlay/overlay_manager.h"
58 #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h"
59 #include "core/components_ng/pattern/relative_container/relative_container_pattern.h"
60 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
61 #include "core/components_ng/pattern/stage/page_pattern.h"
62 #include "core/components_ng/pattern/text/text_layout_property.h"
63 #include "core/components_ng/pattern/text/text_pattern.h"
64 #include "core/components_ng/property/calc_length.h"
65 #include "core/components_ng/property/measure_property.h"
66 #include "core/components_v2/inspector/inspector_constants.h"
67 #include "core/event/key_event.h"
68 #include "core/event/touch_event.h"
69 #include "core/pipeline/base/element_register.h"
70 #include "core/pipeline_ng/pipeline_context.h"
71 
72 namespace OHOS::Ace::NG {
73 
74 namespace {
75 constexpr int32_t SHEET_INFO_IDX = -2;
76 constexpr Dimension SHEET_IMAGE_MARGIN = 16.0_vp;
77 constexpr Dimension SHEET_DIVIDER_WIDTH = 1.0_px;
78 constexpr Dimension SHEET_LIST_PADDING = 24.0_vp;
79 constexpr Dimension DIALOG_BUTTON_TEXT_SIZE = 16.0_fp;
80 constexpr Color DEFAULT_BUTTON_COLOR = Color(0xff007dff);
81 const CalcLength SHEET_IMAGE_SIZE(40.0_vp);
82 constexpr int32_t THREE_BUTTON_MODE = 3;
83 constexpr int32_t TWO_BUTTON_MODE = 2;
84 constexpr int32_t ONE_BUTTON_MODE = 1;
85 constexpr int32_t START_CHILD_INDEX = 0;
86 constexpr uint32_t DIALOG_TITLE_MAXLINES = 1;
87 constexpr Dimension DIALOG_ONE_TITLE_ALL_HEIGHT = 56.0_vp;
88 constexpr Dimension DIALOG_TITLE_CONTENT_HEIGHT = 35.0_px;
89 constexpr int32_t DIALOG_TITLE_AVE_BY_2 = 2;
90 constexpr Dimension DIALOG_CONTENT_PADDING_TOP = 0.0_vp;
91 constexpr Dimension DIALOG_SUBTITLE_PADDING_LEFT = 24.0_vp;
92 constexpr Dimension DIALOG_SUBTITLE_PADDING_RIGHT = 24.0_vp;
93 constexpr Dimension DIALOG_TWO_TITLE_ZERO_SPACE = 0.0_vp;
94 constexpr Dimension DIALOG_TWO_TITLE_SPACE = 16.0_vp;
95 constexpr Dimension ADAPT_TITLE_MIN_FONT_SIZE = 16.0_fp;
96 constexpr Dimension ADAPT_SUBTITLE_MIN_FONT_SIZE = 12.0_fp;
97 constexpr uint32_t ADAPT_TITLE_MAX_LINES = 2;
98 constexpr Dimension DIALOG_BUTTON_BORDER_RADIUS = 20.0_vp;
99 
GetBoolStr(bool isTure)100 std::string GetBoolStr(bool isTure)
101 {
102     return isTure ? "True" : "False";
103 }
104 } // namespace
105 
OnModifyDone()106 void DialogPattern::OnModifyDone()
107 {
108     Pattern::OnModifyDone();
109     auto host = GetHost();
110     CHECK_NULL_VOID(host);
111     auto gestureHub = host->GetOrCreateGestureEventHub();
112     CHECK_NULL_VOID(gestureHub);
113 
114     if (!onClick_) {
115         InitClickEvent(gestureHub);
116     }
117     auto focusHub = host->GetOrCreateFocusHub();
118     CHECK_NULL_VOID(focusHub);
119     RegisterOnKeyEvent(focusHub);
120     InitFocusEvent(focusHub);
121 }
122 
OnAttachToFrameNode()123 void DialogPattern::OnAttachToFrameNode()
124 {
125     auto host = GetHost();
126     CHECK_NULL_VOID(host);
127     auto pipelineContext = host->GetContext();
128     CHECK_NULL_VOID(pipelineContext);
129     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
130     InitHostWindowRect();
131     auto foldModeChangeCallback = [weak = WeakClaim(this)](FoldDisplayMode foldDisplayMode) {
132         auto pattern = weak.Upgrade();
133         CHECK_NULL_VOID(pattern);
134         pattern->isFoldStatusChanged_ = true;
135     };
136     auto callbackId = pipelineContext->RegisterFoldDisplayModeChangedCallback(std::move(foldModeChangeCallback));
137     UpdateFoldDisplayModeChangedCallbackId(callbackId);
138     RegisterHoverModeChangeCallback();
139 }
140 
RegisterHoverModeChangeCallback()141 void DialogPattern::RegisterHoverModeChangeCallback()
142 {
143     auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
144         auto pattern = weak.Upgrade();
145         CHECK_NULL_VOID(pattern);
146         auto host = pattern->GetHost();
147         CHECK_NULL_VOID(host);
148         auto context = host->GetContext();
149         CHECK_NULL_VOID(context);
150         AnimationOption optionPosition;
151         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
152         optionPosition.SetCurve(motion);
153         context->FlushUITasks();
154         context->Animate(optionPosition, motion, [host, context]() {
155             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
156             context->FlushUITasks();
157         });
158     };
159     auto host = GetHost();
160     CHECK_NULL_VOID(host);
161     auto context = host->GetContext();
162     CHECK_NULL_VOID(context);
163     auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
164     UpdateHoverModeChangedCallbackId(hoverModeCallId);
165 }
166 
OnDetachFromFrameNode(FrameNode * frameNode)167 void DialogPattern::OnDetachFromFrameNode(FrameNode* frameNode)
168 {
169     auto pipeline = PipelineContext::GetCurrentContext();
170     CHECK_NULL_VOID(pipeline);
171     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
172     if (HasFoldDisplayModeChangedCallbackId()) {
173         pipeline->UnRegisterFoldDisplayModeChangedCallback(foldDisplayModeChangedCallbackId_.value_or(-1));
174     }
175     if (HasHoverModeChangedCallbackId()) {
176         pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
177     }
178 }
179 
OnFontConfigurationUpdate()180 void DialogPattern::OnFontConfigurationUpdate()
181 {
182     CHECK_NULL_VOID(buttonContainer_);
183     UpdatePropertyForElderly(dialogProperties_.buttons);
184     contentColumn_->RemoveChild(buttonContainer_);
185     auto buttonContainer = BuildButtons(dialogProperties_.buttons, dialogProperties_.buttonDirection);
186     CHECK_NULL_VOID(buttonContainer);
187     buttonContainer->MountToParent(contentColumn_);
188     UpdateTextFontScale();
189     if (isSuitableForElderly_ && NeedsButtonDirectionChange(dialogProperties_.buttons)) {
190         contentColumn_->RemoveChild(buttonContainer_);
191         auto buttonContainerNew = BuildButtons(dialogProperties_.buttons, DialogButtonDirection::VERTICAL);
192         CHECK_NULL_VOID(buttonContainerNew);
193         buttonContainerNew->MountToParent(contentColumn_);
194         buttonContainer_ = buttonContainerNew;
195         CheckScrollHeightIsNegative(contentColumn_, dialogProperties_);
196         UpdateTextFontScale();
197     }
198 }
199 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)200 void DialogPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
201 {
202     GestureEventFunc task = [weak = WeakClaim(this)](const GestureEvent& info) {
203         auto pattern = weak.Upgrade();
204         CHECK_NULL_VOID(pattern);
205         pattern->HandleClick(info);
206     };
207     onClick_ = MakeRefPtr<ClickEvent>(std::move(task));
208     gestureHub->AddClickEvent(onClick_);
209 }
210 
HandleClick(const GestureEvent & info)211 void DialogPattern::HandleClick(const GestureEvent& info)
212 {
213     if (info.GetSourceDevice() == SourceType::KEYBOARD) {
214         return;
215     }
216     auto host = GetHost();
217     CHECK_NULL_VOID(host);
218     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
219     CHECK_NULL_VOID(props);
220     auto globalOffset = host->GetPaintRectOffset(false, true);
221     auto autoCancel = props->GetAutoCancel().value_or(true);
222     if (autoCancel) {
223         auto content = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
224         CHECK_NULL_VOID(content);
225         auto contentRect = content->GetGeometryNode()->GetFrameRect();
226         // close dialog if clicked outside content rect
227         auto&& clickPosition = info.GetGlobalLocation();
228         if (!contentRect.IsInRegion(
229             PointF(clickPosition.GetX() - globalOffset.GetX(), clickPosition.GetY() - globalOffset.GetY()))) {
230             auto overlayManager = GetOverlayManager(nullptr);
231             CHECK_NULL_VOID(overlayManager);
232             if (this->CallDismissInNDK(static_cast<int32_t>(DialogDismissReason::DIALOG_TOUCH_OUTSIDE))) {
233                 return;
234             } else if (this->ShouldDismiss()) {
235                 overlayManager->SetDismissDialogId(host->GetId());
236                 DialogManager::GetInstance().SetDismissDialogInfo(host->GetId(), host->GetTag());
237                 this->CallOnWillDismiss(static_cast<int32_t>(DialogDismissReason::DIALOG_TOUCH_OUTSIDE));
238                 TAG_LOGI(AceLogTag::ACE_DIALOG, "Dialog Should Dismiss");
239                 return;
240             }
241             PopDialog(-1);
242             if (overlayManager->isMaskNode(GetHost()->GetId())) {
243                 overlayManager->PopModalDialog(GetHost()->GetId());
244             }
245         }
246     }
247 }
248 
PopDialog(int32_t buttonIdx=-1)249 void DialogPattern::PopDialog(int32_t buttonIdx = -1)
250 {
251     auto host = GetHost();
252     CHECK_NULL_VOID(host);
253     auto overlayManager = GetOverlayManager(host);
254     CHECK_NULL_VOID(overlayManager);
255 
256     if (host->IsRemoving()) {
257         return;
258     }
259 
260     auto hub = host->GetEventHub<DialogEventHub>();
261     if (buttonIdx != -1) {
262         hub->FireSuccessEvent(buttonIdx);
263         RecordEvent(buttonIdx);
264     } else {
265         // trigger onCancel callback
266         hub->FireCancelEvent();
267         RecordEvent(buttonIdx);
268     }
269     if (dialogProperties_.isShowInSubWindow) {
270         auto container = Container::Current();
271         CHECK_NULL_VOID(container);
272         auto currentId = Container::CurrentId();
273         if (!container->IsSubContainer()) {
274             currentId = SubwindowManager::GetInstance()->GetSubContainerId(currentId);
275         }
276 
277         SubwindowManager::GetInstance()->DeleteHotAreas(currentId, host->GetId());
278         SubwindowManager::GetInstance()->HideDialogSubWindow(currentId);
279     }
280     overlayManager->CloseDialog(host);
281 }
282 
RecordEvent(int32_t btnIndex) const283 void DialogPattern::RecordEvent(int32_t btnIndex) const
284 {
285     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
286         return;
287     }
288     std::string btnText;
289     if (btnIndex >= 0 && static_cast<size_t>(btnIndex) < dialogProperties_.buttons.size()) {
290         btnText = dialogProperties_.buttons.at(btnIndex).text;
291     }
292     Recorder::EventType eventType;
293     if (btnIndex == -1) {
294         eventType = Recorder::EventType::DIALOG_CANCEL;
295     } else {
296         eventType = Recorder::EventType::DIALOG_ACTION;
297     }
298     Recorder::EventParamsBuilder builder;
299     builder.SetEventType(eventType)
300         .SetText(btnText)
301         .SetExtra(Recorder::KEY_TITLE, title_)
302         .SetExtra(Recorder::KEY_SUB_TITLE, subtitle_);
303     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
304 }
305 
306 // set render context properties of content frame
UpdateContentRenderContext(const RefPtr<FrameNode> & contentNode,const DialogProperties & props)307 void DialogPattern::UpdateContentRenderContext(const RefPtr<FrameNode>& contentNode, const DialogProperties& props)
308 {
309     auto contentRenderContext = contentNode->GetRenderContext();
310     CHECK_NULL_VOID(contentRenderContext);
311     contentRenderContext_ = contentRenderContext;
312     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
313         contentRenderContext->IsUniRenderEnabled() && props.isSysBlurStyle) {
314         BlurStyleOption styleOption;
315         styleOption.blurStyle = static_cast<BlurStyle>(
316             props.backgroundBlurStyle.value_or(static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)));
317         contentRenderContext->UpdateBackBlurStyle(styleOption);
318         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(Color::TRANSPARENT));
319     } else {
320         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(dialogTheme_->GetBackgroundColor()));
321     }
322     if (props.borderRadius.has_value()) {
323         if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE)) {
324             auto radiusValue = props.borderRadius.value();
325             ParseBorderRadius(radiusValue);
326             contentRenderContext->UpdateBorderRadius(radiusValue);
327         } else {
328             contentRenderContext->UpdateBorderRadius(props.borderRadius.value());
329         }
330     } else {
331         BorderRadiusProperty radius;
332         radius.SetRadius(dialogTheme_->GetRadius().GetX());
333         contentRenderContext->UpdateBorderRadius(radius);
334     }
335     if (props.borderWidth.has_value()) {
336         auto layoutProps = contentNode->GetLayoutProperty<LinearLayoutProperty>();
337         CHECK_NULL_VOID(layoutProps);
338         layoutProps->UpdateBorderWidth(props.borderWidth.value());
339         contentRenderContext->UpdateBorderWidth(props.borderWidth.value());
340         contentNodeMap_[DialogContentNode::BORDERWIDTH] = contentNode;
341     }
342     if (props.borderStyle.has_value()) {
343         contentRenderContext->UpdateBorderStyle(props.borderStyle.value());
344     }
345     if (props.borderColor.has_value()) {
346         contentRenderContext->UpdateBorderColor(props.borderColor.value());
347     }
348     if (props.shadow.has_value()) {
349         contentRenderContext->UpdateBackShadow(props.shadow.value());
350     }
351     contentRenderContext->SetClipToBounds(true);
352 }
353 
ParseBorderRadius(BorderRadiusProperty & raidus)354 void DialogPattern::ParseBorderRadius(BorderRadiusProperty& raidus)
355 {
356     if (!raidus.radiusTopLeft.has_value() || raidus.radiusTopLeft.value().Value() < 0) {
357         raidus.radiusTopLeft = dialogTheme_->GetRadius().GetX();
358     }
359     if (!raidus.radiusTopRight.has_value() || raidus.radiusTopRight.value().Value() < 0) {
360         raidus.radiusTopRight = dialogTheme_->GetRadius().GetX();
361     }
362     if (!raidus.radiusBottomLeft.has_value() || raidus.radiusBottomLeft.value().Value() < 0) {
363         raidus.radiusBottomLeft = dialogTheme_->GetRadius().GetX();
364     }
365     if (!raidus.radiusBottomRight.has_value() || raidus.radiusBottomRight.value().Value() < 0) {
366         raidus.radiusBottomRight = dialogTheme_->GetRadius().GetX();
367     }
368 }
369 
CreateDialogScroll(const DialogProperties & dialogProps)370 RefPtr<FrameNode> DialogPattern::CreateDialogScroll(const DialogProperties& dialogProps)
371 {
372     auto scroll = FrameNode::CreateFrameNode(
373         V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
374     CHECK_NULL_RETURN(scroll, nullptr);
375     auto props = scroll->GetLayoutProperty<ScrollLayoutProperty>();
376     props->UpdateAxis(Axis::VERTICAL);
377     props->UpdateAlignment(Alignment::CENTER_LEFT);
378     // If title not exist, set scroll align center so that text align center.
379     auto scrollFlexAlign = dialogTheme_->GetScrollFlexAlign();
380     if ((dialogProps.title.empty() && dialogProps.subtitle.empty())) {
381         scrollFlexAlign = FlexAlign::CENTER;
382     }
383     props->UpdateAlignSelf(scrollFlexAlign);
384     return scroll;
385 }
386 
BuildChild(const DialogProperties & props)387 void DialogPattern::BuildChild(const DialogProperties& props)
388 {
389     UpdatePropertyForElderly(props.buttons);
390     // append customNode
391     auto customNode = customNode_.Upgrade();
392     if (customNode) {
393         BuildCustomChild(props, customNode);
394         return;
395     }
396     // Make dialog Content Column
397     auto contentColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
398         AceType::MakeRefPtr<LinearLayoutPattern>(true));
399     CHECK_NULL_VOID(contentColumn);
400 
401     if (!props.title.empty() || !props.subtitle.empty()) {
402         auto title = BuildTitle(props);
403         CHECK_NULL_VOID(title);
404         titleContainer_ = title;
405         contentColumn->AddChild(title);
406     }
407 
408     if (!props.content.empty()) {
409         auto content = BuildContent(props);
410         CHECK_NULL_VOID(content);
411         // create a scroll
412         auto scroll = CreateDialogScroll(props);
413         CHECK_NULL_VOID(scroll);
414         content->MountToParent(scroll);
415         scroll->MountToParent(contentColumn);
416         scroll->MarkModifyDone();
417     }
418 
419     if (!props.customStyle) {
420         UpdateContentRenderContext(contentColumn, props);
421         if (props.height.has_value()) {
422             auto layoutProps = contentColumn->GetLayoutProperty<LinearLayoutProperty>();
423             CHECK_NULL_VOID(layoutProps);
424             layoutProps->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
425             layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
426         }
427     }
428 
429     auto columnProp = AceType::DynamicCast<LinearLayoutProperty>(contentColumn->GetLayoutProperty());
430     CHECK_NULL_VOID(columnProp);
431     // content is full screen in Watch mode
432     auto measureType = dialogTheme_->GetColumnMeasureType();
433     columnProp->UpdateMeasureType(measureType);
434 
435     // build ActionSheet child
436     if (props.type == DialogType::ACTION_SHEET && !props.sheetsInfo.empty()) {
437         auto sheetContainer = BuildSheet(props.sheetsInfo);
438         contentNodeMap_[DialogContentNode::SHEET] = sheetContainer;
439         CHECK_NULL_VOID(sheetContainer);
440         sheetContainer->MountToParent(contentColumn);
441         // scrollable
442         sheetContainer->MarkModifyDone();
443     }
444 
445     // Make Menu node if hasMenu (actionMenu)
446     if (props.isMenu) {
447         bool hasTitle = !props.title.empty() || !props.subtitle.empty();
448         auto menu = BuildMenu(props.buttons, hasTitle);
449         CHECK_NULL_VOID(menu);
450         menu->MountToParent(contentColumn);
451     } else {
452         // build buttons
453         if (!props.buttons.empty()) {
454             auto buttonContainer = BuildButtons(props.buttons, props.buttonDirection);
455             CHECK_NULL_VOID(buttonContainer);
456             buttonContainer->MountToParent(contentColumn);
457         }
458     }
459 
460     auto dialog = GetHost();
461     contentColumn->MountToParent(dialog);
462     UpdateTextFontScale();
463     if (isSuitableForElderly_ && NeedsButtonDirectionChange(props.buttons)) {
464         //remove buttonContainer when Button text is too long
465         contentColumn->RemoveChild(buttonContainer_);
466         auto buttonContainerNew = BuildButtons(props.buttons, DialogButtonDirection::VERTICAL);
467         buttonContainerNew->MountToParent(contentColumn);
468         buttonContainer_ = buttonContainerNew;
469         CheckScrollHeightIsNegative(contentColumn, props);
470     }
471     contentColumn_ = contentColumn;
472     UpdateTextFontScale();
473 }
474 
BuildCustomChild(const DialogProperties & props,const RefPtr<UINode> & customNode)475 void DialogPattern::BuildCustomChild(const DialogProperties& props, const RefPtr<UINode>& customNode)
476 {
477     auto contentWrapper = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
478         AceType::MakeRefPtr<LinearLayoutPattern>(true));
479     CHECK_NULL_VOID(contentWrapper);
480     if (!props.customStyle) {
481         UpdateContentRenderContext(contentWrapper, props);
482     }
483     customNode->MountToParent(contentWrapper);
484     auto dialog = GetHost();
485     contentWrapper->MountToParent(dialog);
486 }
487 
BuildMainTitle(const DialogProperties & dialogProperties)488 RefPtr<FrameNode> DialogPattern::BuildMainTitle(const DialogProperties& dialogProperties)
489 {
490     auto title = FrameNode::CreateFrameNode(
491         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
492     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(title->GetLayoutProperty());
493     CHECK_NULL_RETURN(titleProp, nullptr);
494     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
495     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
496     std::string titleContent = dialogProperties.title.empty() ? dialogProperties.subtitle : dialogProperties.title;
497     titleProp->UpdateContent(titleContent);
498     auto titleStyle = dialogTheme_->GetTitleTextStyle();
499     titleProp->UpdateFontSize(titleStyle.GetFontSize());
500     titleProp->UpdateFontWeight(titleStyle.GetFontWeight());
501     titleProp->UpdateTextColor(titleStyle.GetTextColor());
502     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
503         titleProp->UpdateAdaptMaxFontSize(dialogTheme_->GetTitleTextStyle().GetFontSize());
504         titleProp->UpdateAdaptMinFontSize(ADAPT_TITLE_MIN_FONT_SIZE);
505         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
506         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
507     }
508     PaddingProperty titlePadding;
509     auto paddingInTheme = (dialogProperties.content.empty() && dialogProperties.buttons.empty())
510                               ? dialogTheme_->GetTitleDefaultPadding()
511                               : dialogTheme_->GetTitleAdjustPadding();
512     titlePadding.left = CalcLength(paddingInTheme.Left());
513     titlePadding.right = CalcLength(paddingInTheme.Right());
514     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
515         titlePadding.top = CalcLength(DIALOG_TWO_TITLE_SPACE);
516         titlePadding.bottom = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
517     } else {
518         auto padding =
519             DIALOG_ONE_TITLE_ALL_HEIGHT - Dimension(DIALOG_TITLE_CONTENT_HEIGHT.ConvertToVp(), DimensionUnit::VP);
520         titlePadding.top = CalcLength(padding / DIALOG_TITLE_AVE_BY_2);
521         titlePadding.bottom = CalcLength(padding / DIALOG_TITLE_AVE_BY_2);
522     }
523     titleProp->UpdatePadding(titlePadding);
524 
525     // XTS inspector value
526     title_ = dialogProperties.title;
527     subtitle_ = dialogProperties.subtitle;
528 
529     auto titleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
530         AceType::MakeRefPtr<LinearLayoutPattern>(false));
531     CHECK_NULL_RETURN(titleRow, nullptr);
532     auto titleRowProps = titleRow->GetLayoutProperty<LinearLayoutProperty>();
533     CHECK_NULL_RETURN(titleRowProps, nullptr);
534     titleRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
535     titleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
536     title->MountToParent(titleRow);
537     title->MarkModifyDone();
538     contentNodeMap_[dialogProperties.title.empty() ? DialogContentNode::SUBTITLE : DialogContentNode::TITLE] = title;
539     return titleRow;
540 }
541 
BuildSubTitle(const DialogProperties & dialogProperties)542 RefPtr<FrameNode> DialogPattern::BuildSubTitle(const DialogProperties& dialogProperties)
543 {
544     auto subtitle = FrameNode::CreateFrameNode(
545         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
546     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(subtitle->GetLayoutProperty());
547     CHECK_NULL_RETURN(titleProp, nullptr);
548     auto titleStyle = dialogTheme_->GetSubTitleTextStyle();
549     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
550     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
551     titleProp->UpdateContent(dialogProperties.subtitle);
552     titleProp->UpdateFontSize(titleStyle.GetFontSize());
553     titleProp->UpdateTextColor(titleStyle.GetTextColor());
554     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
555         titleProp->UpdateAdaptMaxFontSize(titleStyle.GetFontSize());
556         titleProp->UpdateAdaptMinFontSize(ADAPT_SUBTITLE_MIN_FONT_SIZE);
557         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
558         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
559     }
560     PaddingProperty titlePadding;
561     titlePadding.left = CalcLength(DIALOG_SUBTITLE_PADDING_LEFT);
562     titlePadding.right = CalcLength(DIALOG_SUBTITLE_PADDING_RIGHT);
563     titlePadding.top = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
564     titlePadding.bottom = CalcLength(DIALOG_TWO_TITLE_SPACE);
565     titleProp->UpdatePadding(titlePadding);
566 
567     // XTS inspector value
568     subtitle_ = dialogProperties.subtitle;
569 
570     auto subtitleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
571         AceType::MakeRefPtr<LinearLayoutPattern>(false));
572     CHECK_NULL_RETURN(subtitleRow, nullptr);
573     auto subtitleRowProps = subtitleRow->GetLayoutProperty<LinearLayoutProperty>();
574     CHECK_NULL_RETURN(subtitleRowProps, nullptr);
575     subtitleRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
576     subtitleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
577     subtitle->MountToParent(subtitleRow);
578     subtitle->MarkModifyDone();
579     contentNodeMap_[DialogContentNode::SUBTITLE] = subtitle;
580     return subtitleRow;
581 }
582 
BuildTitle(const DialogProperties & dialogProperties)583 RefPtr<FrameNode> DialogPattern::BuildTitle(const DialogProperties& dialogProperties)
584 {
585     auto titleRow = BuildMainTitle(dialogProperties);
586     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
587         auto titleColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
588             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
589         CHECK_NULL_RETURN(titleColumn, nullptr);
590         auto columnProps = titleColumn->GetLayoutProperty<LinearLayoutProperty>();
591         CHECK_NULL_RETURN(columnProps, nullptr);
592         columnProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
593         columnProps->UpdateMeasureType(MeasureType::MATCH_CONTENT);
594         auto subtitleRow = BuildSubTitle(dialogProperties);
595         titleColumn->AddChild(titleRow);
596         titleColumn->AddChild(subtitleRow);
597         return titleColumn;
598     }
599     return titleRow;
600 }
601 
BuildContent(const DialogProperties & props)602 RefPtr<FrameNode> DialogPattern::BuildContent(const DialogProperties& props)
603 {
604     // Make Content node
605     auto contentNode = FrameNode::CreateFrameNode(
606         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
607     auto contentProp = AceType::DynamicCast<TextLayoutProperty>(contentNode->GetLayoutProperty());
608     CHECK_NULL_RETURN(contentProp, nullptr);
609     // textAlign always align start. When text line count 1 and title doesn't exist, set text center position.
610     contentProp->UpdateTextAlign(TextAlign::START);
611     contentProp->UpdateContent(props.content);
612     auto contentStyle = dialogTheme_->GetContentTextStyle();
613     contentProp->UpdateFontSize(contentStyle.GetFontSize());
614     contentProp->UpdateTextColor(contentStyle.GetTextColor());
615     // update padding
616     Edge contentPaddingInTheme;
617     PaddingProperty contentPadding;
618     if (!props.title.empty() || !props.subtitle.empty()) {
619         contentPaddingInTheme =
620             props.buttons.empty() ? dialogTheme_->GetDefaultPadding() : dialogTheme_->GetAdjustPadding();
621         contentPadding.top = CalcLength(DIALOG_CONTENT_PADDING_TOP);
622     } else {
623         contentPaddingInTheme =
624             props.buttons.empty() ? dialogTheme_->GetContentDefaultPadding() : dialogTheme_->GetContentAdjustPadding();
625         contentPadding.top = CalcLength(contentPaddingInTheme.Top());
626     }
627     contentPadding.left = CalcLength(contentPaddingInTheme.Left());
628     contentPadding.right = CalcLength(contentPaddingInTheme.Right());
629     contentPadding.bottom = CalcLength(contentPaddingInTheme.Bottom());
630     contentProp->UpdatePadding(contentPadding);
631 
632     // XTS inspector value
633     message_ = props.content;
634     contentNode->MarkModifyDone();
635     contentNodeMap_[DialogContentNode::MESSAGE] = contentNode;
636     return contentNode;
637 }
638 
639 // to close dialog when clicked, use button index in Prompt to trigger success callback
BindCloseCallBack(const RefPtr<GestureEventHub> & hub,int32_t buttonIdx)640 void DialogPattern::BindCloseCallBack(const RefPtr<GestureEventHub>& hub, int32_t buttonIdx)
641 {
642     auto host = GetHost();
643     auto closeCallback = [weak = WeakClaim(RawPtr(host)), buttonIdx](GestureEvent& /*info*/) {
644         auto dialog = weak.Upgrade();
645         CHECK_NULL_VOID(dialog);
646         dialog->GetPattern<DialogPattern>()->PopDialog(buttonIdx);
647     };
648 
649     hub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
650 }
651 
ParseButtonFontColorAndBgColor(const ButtonInfo & params,std::string & textColor,std::optional<Color> & bgColor)652 void DialogPattern::ParseButtonFontColorAndBgColor(
653     const ButtonInfo& params, std::string& textColor, std::optional<Color>& bgColor)
654 {
655     // Parse Button Style
656     if (params.dlgButtonStyle.has_value()) {
657         switch (params.dlgButtonStyle.value()) {
658             case DialogButtonStyle::DEFAULT:
659                 textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
660                 bgColor = dialogTheme_->GetButtonDefaultBgColor();
661                 break;
662             case DialogButtonStyle::HIGHTLIGHT:
663                 textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
664                 bgColor = dialogTheme_->GetButtonHighlightBgColor();
665                 break;
666             default:
667                 break;
668         }
669     }
670 
671     // font color and background color
672     if (!params.textColor.empty()) {
673         textColor = params.textColor;
674     }
675     if (params.isBgColorSetted) {
676         bgColor = params.bgColor;
677     }
678 
679     // Parse default focus
680     if (textColor.empty()) {
681         if (params.defaultFocus && isFirstDefaultFocus_) {
682             textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
683         } else {
684             textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
685         }
686     }
687     if (!bgColor.has_value()) {
688         if (params.defaultFocus && isFirstDefaultFocus_) {
689             bgColor = dialogTheme_->GetButtonHighlightBgColor();
690             isFirstDefaultFocus_ = false;
691         } else {
692             bgColor = dialogTheme_->GetButtonDefaultBgColor();
693         }
694     }
695 }
696 
CreateButton(const ButtonInfo & params,int32_t index,bool isCancel,bool isVertical,int32_t length)697 RefPtr<FrameNode> DialogPattern::CreateButton(
698     const ButtonInfo& params, int32_t index, bool isCancel, bool isVertical, int32_t length)
699 {
700     auto buttonNode = FrameNode::CreateFrameNode(
701         V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ButtonPattern>());
702     CHECK_NULL_RETURN(buttonNode, nullptr);
703     UpdateDialogButtonProperty(buttonNode, index, isVertical, length);
704     // parse button text color and background color
705     std::string textColor;
706     std::optional<Color> bgColor;
707     isFirstDefaultFocus_ = true;
708     ParseButtonFontColorAndBgColor(params, textColor, bgColor);
709 
710     // append text inside button
711     auto textNode = CreateButtonText(params.text, textColor);
712     CHECK_NULL_RETURN(textNode, nullptr);
713     textNode->MountToParent(buttonNode);
714     textNode->MarkModifyDone();
715 
716     SetButtonEnabled(buttonNode, params.enabled);
717 
718     auto hub = buttonNode->GetOrCreateGestureEventHub();
719     CHECK_NULL_RETURN(hub, nullptr);
720     // bind click event
721     if (params.action) {
722         hub->AddClickEvent(params.action);
723     }
724 
725     if (params.isPrimary) {
726         auto focusHub = buttonNode->GetFocusHub();
727         CHECK_NULL_RETURN(focusHub, nullptr);
728         focusHub->SetIsDefaultFocus(params.isPrimary);
729     }
730 
731     // to close dialog when clicked inside button rect
732     if (!isCancel) {
733         BindCloseCallBack(hub, index);
734     } else {
735         BindCloseCallBack(hub, -1);
736     }
737 
738     // add scale animation
739     auto inputHub = buttonNode->GetOrCreateInputEventHub();
740     CHECK_NULL_RETURN(inputHub, nullptr);
741     inputHub->SetHoverEffect(HoverEffectType::AUTO);
742 
743     // update background color
744     auto renderContext = buttonNode->GetRenderContext();
745     CHECK_NULL_RETURN(renderContext, nullptr);
746     renderContext->UpdateBackgroundColor(bgColor.value());
747 
748     // set button default height
749     auto layoutProps = buttonNode->GetLayoutProperty();
750     CHECK_NULL_RETURN(layoutProps, nullptr);
751     auto pipeline = PipelineContext::GetCurrentContext();
752     CHECK_NULL_RETURN(pipeline, nullptr);
753     auto theme = pipeline->GetTheme<ButtonTheme>();
754     CHECK_NULL_RETURN(theme, nullptr);
755     if (!isSuitableForElderly_) {
756         layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(theme->GetHeight())));
757     }
758     return buttonNode;
759 }
760 
UpdateDialogButtonProperty(RefPtr<FrameNode> & buttonNode,int32_t index,bool isVertical,int32_t length)761 void DialogPattern::UpdateDialogButtonProperty(
762     RefPtr<FrameNode>& buttonNode, int32_t index, bool isVertical, int32_t length)
763 {
764     // update button padding
765     auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
766     buttonProp->UpdateType(ButtonType::NORMAL);
767     buttonProp->UpdateBorderRadius(BorderRadiusProperty(DIALOG_BUTTON_BORDER_RADIUS));
768     PaddingProperty buttonPadding;
769     buttonPadding.left = CalcLength(SHEET_LIST_PADDING);
770     buttonPadding.right = CalcLength(SHEET_LIST_PADDING);
771     buttonProp->UpdatePadding(buttonPadding);
772 
773     if (!isVertical) {
774         // set flex grow to fill horizontal space
775         buttonProp->UpdateLayoutWeight(1);
776         buttonProp->UpdateFlexGrow(1.0);
777         buttonProp->UpdateFlexShrink(1.0);
778         if (isSuitableForElderly_ && index != 0) {
779             MarginProperty margin = {
780                 .left = CalcLength(dialogTheme_->GetMarginLeft()),
781             };
782             buttonProp->UpdateMargin(margin);
783         }
784     } else if (isVertical && index != (length - 1)) {
785         // update button space in vertical
786         auto buttonSpace = dialogTheme_->GetMutiButtonPaddingVertical();
787         MarginProperty margin = {
788             .bottom = CalcLength(buttonSpace),
789         };
790         buttonProp->UpdateMargin(margin);
791     }
792 }
793 
CreateDivider(const Dimension & dividerLength,const Dimension & dividerWidth,const Color & color,const Dimension & space)794 RefPtr<FrameNode> DialogPattern::CreateDivider(
795     const Dimension& dividerLength, const Dimension& dividerWidth, const Color& color, const Dimension& space)
796 {
797     auto dividerNode = FrameNode::CreateFrameNode(
798         V2::DIVIDER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<DividerPattern>());
799     CHECK_NULL_RETURN(dividerNode, nullptr);
800     auto dividerProps = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
801     CHECK_NULL_RETURN(dividerProps, nullptr);
802     dividerProps->UpdateVertical(true);
803     dividerProps->UpdateStrokeWidth(dividerWidth);
804     dividerProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(dividerLength)));
805     auto dividerPaintProps = dividerNode->GetPaintProperty<DividerRenderProperty>();
806     CHECK_NULL_RETURN(dividerPaintProps, nullptr);
807     dividerPaintProps->UpdateDividerColor(color);
808 
809     // add divider margin
810     MarginProperty margin = {
811         .left = CalcLength((space - dividerWidth) / 2),
812         .right = CalcLength((space - dividerWidth) / 2),
813     };
814     dividerProps->UpdateMargin(margin);
815     return dividerNode;
816 }
817 
818 // alert dialog buttons
BuildButtons(const std::vector<ButtonInfo> & buttons,const DialogButtonDirection & direction)819 RefPtr<FrameNode> DialogPattern::BuildButtons(
820     const std::vector<ButtonInfo>& buttons, const DialogButtonDirection& direction)
821 {
822     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
823     RefPtr<FrameNode> container;
824     bool isVertical;
825     if (direction == DialogButtonDirection::HORIZONTAL ||
826         (direction == DialogButtonDirection::AUTO && buttons.size() == TWO_BUTTON_MODE)) {
827         // use horizontal layout
828         isVertical = false;
829         container = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(false));
830         CHECK_NULL_RETURN(container, nullptr);
831         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
832         layoutProps->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
833         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
834     } else {
835         // use vertical layout
836         isVertical = true;
837         container = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(true));
838         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
839         layoutProps->UpdateCrossAxisAlign(FlexAlign::STRETCH);
840         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
841     }
842     CHECK_NULL_RETURN(container, nullptr);
843     // set action's padding
844     PaddingProperty actionPadding;
845     if (buttons.size() == ONE_BUTTON_MODE || isVertical) {
846         actionPadding.left = CalcLength(dialogTheme_->GetSingleButtonPaddingStart());
847         actionPadding.right = CalcLength(dialogTheme_->GetSingleButtonPaddingEnd());
848     } else {
849         actionPadding.left = CalcLength(dialogTheme_->GetMutiButtonPaddingStart());
850         actionPadding.right = CalcLength(dialogTheme_->GetMutiButtonPaddingEnd());
851     }
852     auto padding = dialogTheme_->GetActionsPadding();
853     actionPadding.top = CalcLength(dialogTheme_->GetButtonWithContentPadding());
854     actionPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
855     container->GetLayoutProperty()->UpdatePadding(actionPadding);
856 
857     AddButtonAndDivider(buttons, container, isVertical);
858     container->MarkModifyDone();
859     buttonContainer_ = container;
860     return container;
861 }
862 
AddButtonAndDivider(const std::vector<ButtonInfo> & buttons,const RefPtr<NG::FrameNode> & container,bool isVertical)863 void DialogPattern::AddButtonAndDivider(
864     const std::vector<ButtonInfo>& buttons, const RefPtr<NG::FrameNode>& container, bool isVertical)
865 {
866     auto dividerLength = dialogTheme_->GetDividerLength();
867     auto dividerWidth = dialogTheme_->GetDividerBetweenButtonWidth_();
868     auto dividerColor = dialogTheme_->GetDividerColor();
869     auto buttonSpace = dialogTheme_->GetMutiButtonPaddingHorizontal();
870     auto length = buttons.size();
871     for (size_t i = 0; i < length; ++i) {
872         if (i != 0 && !isVertical && !isSuitableForElderly_) {
873             auto dividerNode = CreateDivider(dividerLength, dividerWidth, dividerColor, buttonSpace);
874             CHECK_NULL_VOID(dividerNode);
875             container->AddChild(dividerNode);
876         }
877         auto buttonNode = CreateButton(buttons[i], i, false, isVertical, length);
878         CHECK_NULL_VOID(buttonNode);
879         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
880         CHECK_NULL_VOID(buttonPattern);
881         buttonPattern->SetSkipColorConfigurationUpdate();
882         buttonNode->MountToParent(container);
883         buttonNode->MarkModifyDone();
884     }
885 }
886 
CreateButtonText(const std::string & text,const std::string & colorStr)887 RefPtr<FrameNode> DialogPattern::CreateButtonText(const std::string& text, const std::string& colorStr)
888 {
889     auto textNode = FrameNode::CreateFrameNode(
890         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
891     CHECK_NULL_RETURN(textNode, nullptr);
892     textNode->GetOrCreateFocusHub()->SetFocusable(true);
893     auto textProps = textNode->GetLayoutProperty<TextLayoutProperty>();
894     CHECK_NULL_RETURN(textProps, nullptr);
895     textProps->UpdateContent(text);
896     textProps->UpdateFontWeight(FontWeight::MEDIUM);
897     textProps->UpdateMaxLines(1);
898     textProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
899     Dimension buttonTextSize =
900         dialogTheme_->GetButtonTextSize().IsValid() ? dialogTheme_->GetButtonTextSize() : DIALOG_BUTTON_TEXT_SIZE;
901     textProps->UpdateFontSize(buttonTextSize);
902 
903     // update text color
904     Color color;
905     if (Color::ParseColorString(colorStr, color)) {
906         textProps->UpdateTextColor(color);
907     } else {
908         textProps->UpdateTextColor(DEFAULT_BUTTON_COLOR);
909     }
910     return textNode;
911 }
912 
BuildSheetItem(const ActionSheetInfo & item)913 RefPtr<FrameNode> DialogPattern::BuildSheetItem(const ActionSheetInfo& item)
914 {
915     // ListItem -> Row -> title + icon
916     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
917     RefPtr<FrameNode> itemNode = FrameNode::CreateFrameNode(
918         V2::LIST_ITEM_ETS_TAG, Id, AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE));
919     CHECK_NULL_RETURN(itemNode, nullptr);
920 
921     // update sheet row flex align
922     auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
923     auto itemRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
924     CHECK_NULL_RETURN(itemRow, nullptr);
925     auto layoutProps = itemRow->GetLayoutProperty<LinearLayoutProperty>();
926     layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
927     layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
928 
929     // mount icon
930     if (!item.icon.empty()) {
931         auto iconNode = BuildSheetInfoIcon(item.icon);
932         iconNode->MountToParent(itemRow);
933         iconNode->MarkModifyDone();
934     }
935 
936     // mount title
937     if (!item.title.empty()) {
938         auto titleNode = BuildSheetInfoTitle(item.title);
939         titleNode->MountToParent(itemRow);
940         titleNode->MarkModifyDone();
941     }
942 
943     // set sheetItem action
944     auto hub = itemRow->GetOrCreateGestureEventHub();
945     if (item.action) {
946         hub->AddClickEvent(item.action);
947         auto recordEvent = [weak = WeakClaim(this), title = item.title](GestureEvent& info) {
948             if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
949                 return;
950             }
951             auto pattern = weak.Upgrade();
952             CHECK_NULL_VOID(pattern);
953             Recorder::EventParamsBuilder builder;
954             builder.SetEventType(Recorder::EventType::DIALOG_SELECT)
955                 .SetText(title)
956                 .SetExtra(Recorder::KEY_TITLE, pattern->title_)
957                 .SetExtra(Recorder::KEY_SUB_TITLE, pattern->subtitle_);
958             Recorder::EventRecorder::Get().OnEvent(std::move(builder));
959         };
960         auto recordEventPtr = MakeRefPtr<ClickEvent>(std::move(recordEvent));
961         hub->AddClickEvent(recordEventPtr);
962     }
963 
964     // close dialog when clicked
965     BindCloseCallBack(hub, SHEET_INFO_IDX);
966     itemRow->MountToParent(itemNode);
967     return itemNode;
968 }
969 
BuildSheetInfoTitle(const std::string & title)970 RefPtr<FrameNode> DialogPattern::BuildSheetInfoTitle(const std::string& title)
971 {
972     auto titleId = ElementRegister::GetInstance()->MakeUniqueId();
973     auto titleNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, titleId, AceType::MakeRefPtr<TextPattern>());
974     CHECK_NULL_RETURN(titleNode, nullptr);
975     // update text style
976     auto style = dialogTheme_->GetContentTextStyle();
977     auto props = titleNode->GetLayoutProperty<TextLayoutProperty>();
978     props->UpdateContent(title);
979     props->UpdateTextOverflow(TextOverflow::ELLIPSIS);
980     props->UpdateAdaptMaxFontSize(style.GetFontSize());
981     props->UpdateAdaptMinFontSize(dialogTheme_->GetTitleMinFontSize());
982     props->UpdateMaxLines(style.GetMaxLines());
983     props->UpdateFlexGrow(1.0f);
984     props->UpdateFlexShrink(1.0f);
985     return titleNode;
986 }
987 
BuildSheetInfoIcon(const std::string & icon)988 RefPtr<FrameNode> DialogPattern::BuildSheetInfoIcon(const std::string& icon)
989 {
990     auto iconId = ElementRegister::GetInstance()->MakeUniqueId();
991     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, iconId, AceType::MakeRefPtr<ImagePattern>());
992     CHECK_NULL_RETURN(iconNode, nullptr);
993     // add image margin
994     MarginProperty margin = {
995         .left = CalcLength(SHEET_IMAGE_MARGIN),
996         .right = CalcLength(SHEET_IMAGE_MARGIN),
997         .top = CalcLength(SHEET_IMAGE_MARGIN),
998         .bottom = CalcLength(SHEET_IMAGE_MARGIN),
999     };
1000     auto iconProps = iconNode->GetLayoutProperty<ImageLayoutProperty>();
1001     iconProps->UpdateMargin(margin);
1002     auto imageSrc = ImageSourceInfo(icon);
1003     iconProps->UpdateImageSourceInfo(imageSrc);
1004     iconProps->UpdateUserDefinedIdealSize(CalcSize(SHEET_IMAGE_SIZE, SHEET_IMAGE_SIZE));
1005     return iconNode;
1006 }
1007 
BuildSheet(const std::vector<ActionSheetInfo> & sheets)1008 RefPtr<FrameNode> DialogPattern::BuildSheet(const std::vector<ActionSheetInfo>& sheets)
1009 {
1010     auto listId = ElementRegister::GetInstance()->MakeUniqueId();
1011     auto list = FrameNode::CreateFrameNode(V2::LIST_ETS_TAG, listId, AceType::MakeRefPtr<ListPattern>());
1012     CHECK_NULL_RETURN(list, nullptr);
1013 
1014     // set sheet padding
1015     CalcLength padding(SHEET_LIST_PADDING.ConvertToPx());
1016     PaddingProperty sheetPadding = {
1017         .left = padding,
1018         .right = padding,
1019         .top = padding,
1020         .bottom = padding,
1021     };
1022     list->GetLayoutProperty()->UpdatePadding(sheetPadding);
1023     list->GetPaintProperty<ScrollablePaintProperty>()->UpdateScrollBarMode(DisplayMode::OFF);
1024 
1025     for (auto&& item : sheets) {
1026         auto itemNode = BuildSheetItem(item);
1027         CHECK_NULL_RETURN(itemNode, nullptr);
1028         list->AddChild(itemNode);
1029     }
1030 
1031     // set list divider
1032     auto divider = V2::ItemDivider {
1033         .strokeWidth = SHEET_DIVIDER_WIDTH,
1034         .color = Color::GRAY,
1035     };
1036     auto props = list->GetLayoutProperty<ListLayoutProperty>();
1037     props->UpdateDivider(divider);
1038     props->UpdateListDirection(Axis::VERTICAL);
1039     return list;
1040 }
1041 
BuildMenu(const std::vector<ButtonInfo> & buttons,bool hasTitle)1042 RefPtr<FrameNode> DialogPattern::BuildMenu(const std::vector<ButtonInfo>& buttons, bool hasTitle)
1043 {
1044     auto menu = FrameNode::CreateFrameNode(
1045         V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(true));
1046     menuNode_ = menu;
1047     // column -> button
1048     const size_t size = buttons.size();
1049     for (size_t i = 0; i < size; ++i) {
1050         RefPtr<FrameNode> button;
1051         uint32_t val = size > 0 ? size - 1 : 0;
1052         if (i != val) {
1053             button = CreateButton(buttons[i], i);
1054         } else {
1055             button = CreateButton(buttons[i], i, true);
1056         }
1057         CHECK_NULL_RETURN(button, nullptr);
1058         auto props = DynamicCast<FrameNode>(button)->GetLayoutProperty();
1059         auto buttonRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1060             AceType::MakeRefPtr<LinearLayoutPattern>(false));
1061         CHECK_NULL_RETURN(buttonRow, nullptr);
1062         auto buttonRowProps = buttonRow->GetLayoutProperty<LinearLayoutProperty>();
1063         CHECK_NULL_RETURN(buttonRowProps, nullptr);
1064         buttonRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
1065         buttonRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
1066 
1067         button->MountToParent(buttonRow);
1068         button->MarkModifyDone();
1069         menu->AddChild(buttonRow);
1070     }
1071     auto menuProps = menu->GetLayoutProperty<LinearLayoutProperty>();
1072     CHECK_NULL_RETURN(menuProps, nullptr);
1073     PaddingProperty menuPadding;
1074     if (!hasTitle) {
1075         menuPadding.top = CalcLength(dialogTheme_->GetContentAdjustPadding().Top());
1076     }
1077     menuPadding.left = CalcLength(dialogTheme_->GetDefaultPadding().Left());
1078     menuPadding.right = CalcLength(dialogTheme_->GetDefaultPadding().Right());
1079     menuPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
1080     menuProps->UpdatePadding(menuPadding);
1081     return menu;
1082 }
1083 
RegisterOnKeyEvent(const RefPtr<FocusHub> & focusHub)1084 void DialogPattern::RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1085 {
1086     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1087         auto pattern = wp.Upgrade();
1088         CHECK_NULL_RETURN(pattern, false);
1089         return pattern->OnKeyEvent(event);
1090     };
1091     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1092 }
1093 
OnKeyEvent(const KeyEvent & event)1094 bool DialogPattern::OnKeyEvent(const KeyEvent& event)
1095 {
1096     if (event.action != KeyAction::DOWN) {
1097         return false;
1098     }
1099     return false;
1100 }
1101 
InitFocusEvent(const RefPtr<FocusHub> & focusHub)1102 void DialogPattern::InitFocusEvent(const RefPtr<FocusHub>& focusHub)
1103 {
1104     auto onFocus = [wp = WeakClaim(this)]() {
1105         auto pattern = wp.Upgrade();
1106         CHECK_NULL_VOID(pattern);
1107         pattern->HandleFocusEvent();
1108     };
1109     focusHub->SetOnFocusInternal(std::move(onFocus));
1110 
1111     auto onBlur = [wp = WeakClaim(this)]() {
1112         auto pattern = wp.Upgrade();
1113         CHECK_NULL_VOID(pattern);
1114         pattern->HandleBlurEvent();
1115     };
1116     focusHub->SetOnBlurInternal(std::move(onBlur));
1117 }
1118 
HandleBlurEvent()1119 void DialogPattern::HandleBlurEvent()
1120 {
1121     CHECK_NULL_VOID(contentRenderContext_ && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE));
1122     auto defaultShadowOff = static_cast<ShadowStyle>(dialogTheme_->GetDefaultShadowOff());
1123     contentRenderContext_->UpdateBackShadow(dialogProperties_.shadow.value_or(Shadow::CreateShadow(defaultShadowOff)));
1124 }
1125 
HandleFocusEvent()1126 void DialogPattern::HandleFocusEvent()
1127 {
1128     CHECK_NULL_VOID(contentRenderContext_ && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE));
1129     auto defaultShadowOn = static_cast<ShadowStyle>(dialogTheme_->GetDefaultShadowOn());
1130     contentRenderContext_->UpdateBackShadow(dialogProperties_.shadow.value_or(Shadow::CreateShadow(defaultShadowOn)));
1131 }
1132 
1133 // XTS inspector
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1134 void DialogPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1135 {
1136     /* no fixed attr below, just return */
1137     if (filter.IsFastFilter()) {
1138         return;
1139     }
1140     auto host = GetHost();
1141     CHECK_NULL_VOID(host);
1142     if (host->GetTag() == V2::ALERT_DIALOG_ETS_TAG || host->GetTag() == V2::ACTION_SHEET_DIALOG_ETS_TAG) {
1143         json->PutExtAttr("title", title_.c_str(), filter);
1144         json->PutExtAttr("subtitle", subtitle_.c_str(), filter);
1145         json->PutExtAttr("message", message_.c_str(), filter);
1146     }
1147 }
1148 
OnColorConfigurationUpdate()1149 void DialogPattern::OnColorConfigurationUpdate()
1150 {
1151     auto host = GetHost();
1152     CHECK_NULL_VOID(host);
1153     auto context = host->GetContext();
1154     CHECK_NULL_VOID(context);
1155     auto dialogTheme = context->GetTheme<DialogTheme>();
1156     CHECK_NULL_VOID(dialogTheme);
1157     dialogTheme_ = dialogTheme;
1158     UpdateWrapperBackgroundStyle(host, dialogTheme);
1159     UpdateButtonsProperty();
1160     OnModifyDone();
1161     host->MarkDirtyNode();
1162 }
1163 
UpdateAlignmentAndOffset()1164 void DialogPattern::UpdateAlignmentAndOffset()
1165 {
1166     auto host = GetHost();
1167     CHECK_NULL_VOID(host);
1168     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1169     CHECK_NULL_VOID(props);
1170     auto dialogProp = GetDialogProperties();
1171     props->UpdateDialogAlignment(dialogProp.alignment);
1172     props->UpdateDialogOffset(dialogProp.offset);
1173 }
1174 
OnLanguageConfigurationUpdate()1175 void DialogPattern::OnLanguageConfigurationUpdate()
1176 {
1177     CHECK_NULL_VOID(dialogProperties_.onLanguageChange);
1178     dialogProperties_.onLanguageChange(dialogProperties_);
1179     UpdateAlignmentAndOffset();
1180     if (!dialogProperties_.title.empty() && contentNodeMap_.find(DialogContentNode::TITLE) != contentNodeMap_.end()) {
1181         UpdateNodeContent(contentNodeMap_[DialogContentNode::TITLE], dialogProperties_.title);
1182         title_ = dialogProperties_.title;
1183     }
1184 
1185     if (!dialogProperties_.subtitle.empty() &&
1186         contentNodeMap_.find(DialogContentNode::SUBTITLE) != contentNodeMap_.end()) {
1187         UpdateNodeContent(contentNodeMap_[DialogContentNode::SUBTITLE], dialogProperties_.subtitle);
1188         subtitle_ = dialogProperties_.subtitle;
1189     }
1190 
1191     if (!dialogProperties_.content.empty() &&
1192         contentNodeMap_.find(DialogContentNode::MESSAGE) != contentNodeMap_.end()) {
1193         UpdateNodeContent(contentNodeMap_[DialogContentNode::MESSAGE], dialogProperties_.content);
1194         message_ = dialogProperties_.content;
1195     }
1196 
1197     if (!dialogProperties_.buttons.empty()) {
1198         UpdateButtonsProperty();
1199     }
1200 
1201     if (dialogProperties_.type == DialogType::ACTION_SHEET) {
1202         UpdateSheetIconAndText();
1203     }
1204 
1205     if (dialogProperties_.shadow.has_value()) {
1206         contentRenderContext_->UpdateBackShadow(dialogProperties_.shadow.value());
1207     }
1208 
1209     if (dialogProperties_.borderWidth.has_value() &&
1210         contentNodeMap_.find(DialogContentNode::BORDERWIDTH) != contentNodeMap_.end()) {
1211         auto layoutProps = contentNodeMap_[DialogContentNode::BORDERWIDTH]->GetLayoutProperty<LinearLayoutProperty>();
1212         layoutProps->UpdateBorderWidth(dialogProperties_.borderWidth.value());
1213         contentRenderContext_->UpdateBorderWidth(dialogProperties_.borderWidth.value());
1214     }
1215 
1216     if (dialogProperties_.borderColor.has_value()) {
1217         contentRenderContext_->UpdateBorderColor(dialogProperties_.borderColor.value());
1218     }
1219 
1220     if (dialogProperties_.borderRadius.has_value()) {
1221         contentRenderContext_->UpdateBorderRadius(dialogProperties_.borderRadius.value());
1222     }
1223 }
1224 
UpdateNodeContent(const RefPtr<FrameNode> & node,std::string & text)1225 void DialogPattern::UpdateNodeContent(const RefPtr<FrameNode>& node, std::string& text)
1226 {
1227     CHECK_NULL_VOID(node);
1228     auto layoutProps = AceType::DynamicCast<TextLayoutProperty>(node->GetLayoutProperty());
1229     CHECK_NULL_VOID(layoutProps);
1230     layoutProps->UpdateContent(text);
1231     node->MarkModifyDone();
1232 }
1233 
UpdateSheetIconAndText()1234 void DialogPattern::UpdateSheetIconAndText()
1235 {
1236     if (dialogProperties_.sheetsInfo.empty()) {
1237         return;
1238     }
1239 
1240     auto sheetContainer = contentNodeMap_[DialogContentNode::SHEET];
1241     CHECK_NULL_VOID(sheetContainer);
1242     int32_t sheetIndex = 0;
1243     for (const auto& sheet : sheetContainer->GetChildren()) {
1244         auto itemRow = DynamicCast<FrameNode>(sheet->GetFirstChild());
1245         CHECK_NULL_VOID(itemRow);
1246 
1247         auto sheetInfo = dialogProperties_.sheetsInfo.at(sheetIndex);
1248         if (!sheetInfo.icon.empty()) {
1249             auto iconNode = DynamicCast<FrameNode>(itemRow->GetFirstChild());
1250             CHECK_NULL_VOID(iconNode);
1251             auto iconProps = iconNode->GetLayoutProperty<ImageLayoutProperty>();
1252             CHECK_NULL_VOID(iconProps);
1253             iconProps->UpdateImageSourceInfo(ImageSourceInfo(sheetInfo.icon));
1254             iconNode->MarkModifyDone();
1255         }
1256         if (!sheetInfo.title.empty()) {
1257             auto titleNode = DynamicCast<FrameNode>(itemRow->GetLastChild());
1258             CHECK_NULL_VOID(titleNode);
1259             auto titleProps = titleNode->GetLayoutProperty<TextLayoutProperty>();
1260             CHECK_NULL_VOID(titleProps);
1261             titleProps->UpdateContent(sheetInfo.title);
1262             titleNode->MarkModifyDone();
1263         }
1264         ++sheetIndex;
1265     }
1266 }
1267 
UpdateButtonsProperty()1268 void DialogPattern::UpdateButtonsProperty()
1269 {
1270     CHECK_NULL_VOID(buttonContainer_);
1271     int32_t btnIndex = 0;
1272     isFirstDefaultFocus_ = true;
1273     for (const auto& buttonNode : buttonContainer_->GetChildren()) {
1274         if (buttonNode->GetTag() != V2::BUTTON_ETS_TAG) {
1275             continue;
1276         }
1277         auto buttonFrameNode = DynamicCast<FrameNode>(buttonNode);
1278         CHECK_NULL_VOID(buttonFrameNode);
1279         auto pattern = buttonFrameNode->GetPattern<ButtonPattern>();
1280         CHECK_NULL_VOID(pattern);
1281         pattern->SetSkipColorConfigurationUpdate();
1282         // parse button text color and background color
1283         std::string textColorStr;
1284         std::optional<Color> bgColor;
1285         ParseButtonFontColorAndBgColor(dialogProperties_.buttons[btnIndex], textColorStr, bgColor);
1286         // update background color
1287         auto renderContext = buttonFrameNode->GetRenderContext();
1288         CHECK_NULL_VOID(renderContext);
1289         renderContext->UpdateBackgroundColor(bgColor.value());
1290         auto buttonTextNode = DynamicCast<FrameNode>(buttonFrameNode->GetFirstChild());
1291         CHECK_NULL_VOID(buttonTextNode);
1292         auto buttonTextLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
1293         CHECK_NULL_VOID(buttonTextLayoutProperty);
1294         Color textColor;
1295         Color::ParseColorString(textColorStr, textColor);
1296         buttonTextLayoutProperty->UpdateContent(dialogProperties_.buttons[btnIndex].text);
1297         buttonTextLayoutProperty->UpdateTextColor(textColor);
1298         buttonTextNode->MarkModifyDone();
1299         buttonTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1300         ++btnIndex;
1301     }
1302 }
1303 
GetDialogContext()1304 PipelineContext* DialogPattern::GetDialogContext()
1305 {
1306     auto host = GetHost();
1307     CHECK_NULL_RETURN(host, nullptr);
1308     auto context = host->GetContext();
1309     CHECK_NULL_RETURN(context, nullptr);
1310     return context;
1311 }
1312 
UpdatePropertyForElderly(const std::vector<ButtonInfo> & buttons)1313 void DialogPattern::UpdatePropertyForElderly(const std::vector<ButtonInfo>& buttons)
1314 {
1315     isSuitableForElderly_ = false;
1316     notAdapationAging_ = false;
1317     auto pipeline = PipelineContext::GetCurrentContext();
1318     CHECK_NULL_VOID(pipeline);
1319     auto windowManager = pipeline->GetWindowManager();
1320     CHECK_NULL_VOID(windowManager);
1321     auto dialogContext = GetDialogContext();
1322     CHECK_NULL_VOID(dialogContext);
1323     TAG_LOGI(AceLogTag::ACE_DIALOG, "dialog GetContext fontScale : %{public}f", dialogContext->GetFontScale());
1324     if (GreatOrEqual(dialogContext->GetFontScale(), dialogTheme_->GetMinFontScaleForElderly())) {
1325         if (pipeline->GetRootHeight() < dialogTheme_->GetDialogLandscapeHeightBoundary().ConvertToPx() &&
1326             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
1327             notAdapationAging_ = true;
1328             return;
1329         }
1330         deviceOrientation_ = SystemProperties::GetDeviceOrientation();
1331         if (buttons.size() >= THREE_BUTTON_MODE && deviceOrientation_ == DeviceOrientation::LANDSCAPE) {
1332             notAdapationAging_ = true;
1333             return;
1334         }
1335         fontScaleForElderly_ = dialogContext->GetFontScale();
1336         isSuitableForElderly_ = true;
1337         notAdapationAging_ = false;
1338     }
1339 }
1340 
NeedsButtonDirectionChange(const std::vector<ButtonInfo> & buttons)1341 bool DialogPattern::NeedsButtonDirectionChange(const std::vector<ButtonInfo>& buttons)
1342 {
1343     CHECK_NULL_RETURN(buttonContainer_, false);
1344     if (buttons.size() == ONE_BUTTON_MODE || buttonContainer_->GetTag() != V2::ROW_ETS_TAG) {
1345         return false;
1346     }
1347     auto host = GetHost();
1348     CHECK_NULL_RETURN(host, false);
1349     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1350     CHECK_NULL_RETURN(props, false);
1351     auto buttonLayoutConstraint = props->GetLayoutConstraint();
1352     isSuitOldMeasure_ = true;
1353     host->Measure(buttonLayoutConstraint);
1354     isSuitOldMeasure_ = false;
1355     const auto& children = buttonContainer_->GetChildren();
1356     for (const auto& child : children) {
1357         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
1358             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1359             CHECK_NULL_RETURN(buttonNode, false);
1360             auto buttonTextNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
1361             CHECK_NULL_RETURN(buttonTextNode, false);
1362             auto textGeometryNode = buttonTextNode->GetGeometryNode();
1363             CHECK_NULL_RETURN(textGeometryNode, false);
1364             auto textFarmeSize = textGeometryNode->GetFrameSize();
1365             auto textPattern = buttonTextNode->GetPattern<TextPattern>();
1366             CHECK_NULL_RETURN(textPattern, false);
1367             auto textDisplay = textPattern->GetTextForDisplay();
1368             auto textProps = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
1369             CHECK_NULL_RETURN(textProps, false);
1370             Dimension buttonTextSize = textProps->GetFontSize().value_or(dialogTheme_->GetButtonTextSize());
1371             MeasureContext measureContext;
1372             measureContext.textContent = textDisplay;
1373             measureContext.fontSize = buttonTextSize;
1374             auto dialogContext = GetDialogContext();
1375             CHECK_NULL_RETURN(dialogContext, false);
1376             if (isSuitableForElderly_ && dialogContext->GetFontScale() >= dialogTheme_->GetTitleMaxFontScale() &&
1377                 SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
1378                 measureContext.fontSize =
1379                     Dimension(buttonTextSize.Value() * dialogTheme_->GetTitleMaxFontScale(), DimensionUnit::VP);
1380             }
1381             auto fontweight = StringUtils::FontWeightToString(FontWeight::MEDIUM);
1382             measureContext.fontWeight = fontweight;
1383             Size measureSize = MeasureUtil::MeasureTextSize(measureContext);
1384             if (measureSize.Width() != textFarmeSize.Width()) {
1385                 return true;
1386             }
1387         }
1388     }
1389     return false;
1390 }
1391 
CheckScrollHeightIsNegative(const RefPtr<UINode> & contentColumn,const DialogProperties & Dialogprops)1392 void DialogPattern::CheckScrollHeightIsNegative(
1393     const RefPtr<UINode>& contentColumn, const DialogProperties& Dialogprops)
1394 {
1395     CHECK_NULL_VOID(buttonContainer_);
1396     if (Dialogprops.buttons.size() == ONE_BUTTON_MODE || buttonContainer_->GetTag() == V2::ROW_ETS_TAG) {
1397         return;
1398     }
1399     auto host = GetHost();
1400     CHECK_NULL_VOID(host);
1401     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
1402     CHECK_NULL_VOID(props);
1403     auto buttonLayoutConstraint = props->GetLayoutConstraint();
1404     isSuitOldMeasure_ = true;
1405     host->Measure(buttonLayoutConstraint);
1406     isSuitOldMeasure_ = false;
1407     if (isScrollHeightNegative_) {
1408         isSuitableForElderly_ = false;
1409         notAdapationAging_ = true;
1410         contentColumn->RemoveChild(buttonContainer_);
1411         auto buttonContainerNew = BuildButtons(Dialogprops.buttons, Dialogprops.buttonDirection);
1412         buttonContainerNew->MountToParent(contentColumn);
1413         buttonContainer_ = buttonContainerNew;
1414     }
1415 }
1416 
UpdateDeviceOrientation(const DeviceOrientation & deviceOrientation)1417 void DialogPattern::UpdateDeviceOrientation(const DeviceOrientation& deviceOrientation)
1418 {
1419     if (deviceOrientation_ != deviceOrientation) {
1420         CHECK_NULL_VOID(buttonContainer_);
1421         OnFontConfigurationUpdate();
1422         auto host = GetHost();
1423         CHECK_NULL_VOID(host);
1424         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1425         deviceOrientation_ = deviceOrientation;
1426     }
1427 }
1428 
UpdateTitleTextFontScale()1429 void DialogPattern::UpdateTitleTextFontScale()
1430 {
1431     CHECK_NULL_VOID(titleContainer_);
1432     auto scale = dialogTheme_->GetMinFontScaleForElderly();
1433     if (isSuitableForElderly_) {
1434         scale = dialogTheme_->GetTitleMaxFontScale();
1435     }
1436     if (titleContainer_->GetTag() == V2::COLUMN_ETS_TAG) {
1437         auto children = titleContainer_->GetChildren();
1438         for (const auto& child : children) {
1439             auto textNode = AceType::DynamicCast<FrameNode>(child->GetChildAtIndex(START_CHILD_INDEX));
1440             CHECK_NULL_VOID(textNode);
1441             auto titleProp = AceType::DynamicCast<TextLayoutProperty>(textNode->GetLayoutProperty());
1442             CHECK_NULL_VOID(titleProp);
1443             if (notAdapationAging_) {
1444                 titleProp->UpdateMaxFontScale(dialogTheme_->GetDialogDefaultScale());
1445             } else {
1446                 titleProp->UpdateMaxFontScale(scale);
1447                 titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
1448             }
1449         }
1450     } else {
1451         auto textNode = AceType::DynamicCast<FrameNode>(titleContainer_->GetChildAtIndex(START_CHILD_INDEX));
1452         CHECK_NULL_VOID(textNode);
1453         auto titleProp = AceType::DynamicCast<TextLayoutProperty>(textNode->GetLayoutProperty());
1454         CHECK_NULL_VOID(titleProp);
1455         if (notAdapationAging_) {
1456             titleProp->UpdateMaxFontScale(dialogTheme_->GetDialogDefaultScale());
1457         } else {
1458             titleProp->UpdateMaxFontScale(scale);
1459             titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
1460         }
1461     }
1462 }
1463 
UpdateTextFontScale()1464 void DialogPattern::UpdateTextFontScale()
1465 {
1466     UpdateTitleTextFontScale();
1467     CHECK_NULL_VOID(contentNodeMap_[DialogContentNode::MESSAGE]);
1468     auto scale = dialogTheme_->GetMinFontScaleForElderly();
1469     auto contentProp =
1470         AceType::DynamicCast<TextLayoutProperty>(contentNodeMap_[DialogContentNode::MESSAGE]->GetLayoutProperty());
1471     CHECK_NULL_VOID(contentProp);
1472     if (isSuitableForElderly_) {
1473         scale = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE
1474                     ? dialogTheme_->GetContentLandscapeMaxFontScale()
1475                     : dialogTheme_->GetContentMaxFontScale();
1476     }
1477     if (notAdapationAging_) {
1478         contentProp->UpdateMaxFontScale(dialogTheme_->GetDialogDefaultScale());
1479     } else {
1480         contentProp->UpdateMaxFontScale(scale);
1481     }
1482     CHECK_NULL_VOID(buttonContainer_);
1483     MarginProperty margin;
1484     if (isSuitableForElderly_) {
1485         scale = SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE
1486                     ? dialogTheme_->GetButtonLandscapeMaxFontScale()
1487                     : dialogTheme_->GetButtonMaxFontScale();
1488         margin.top = CalcLength(8.0_vp);
1489         margin.bottom = CalcLength(8.0_vp);
1490     }
1491     const auto& children = buttonContainer_->GetChildren();
1492     for (const auto& child : children) {
1493         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
1494             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1495             CHECK_NULL_VOID(buttonNode);
1496             auto buttonTextNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
1497             CHECK_NULL_VOID(buttonTextNode);
1498             auto textProp = AceType::DynamicCast<TextLayoutProperty>(buttonTextNode->GetLayoutProperty());
1499             CHECK_NULL_VOID(textProp);
1500             if (notAdapationAging_) {
1501                 textProp->UpdateMaxFontScale(dialogTheme_->GetDialogDefaultScale());
1502             } else {
1503                 textProp->UpdateMaxFontScale(scale);
1504             }
1505             if (isSuitableForElderly_) {
1506                 textProp->UpdateMargin(margin);
1507             }
1508         }
1509     }
1510 }
1511 
UpdateFontScale()1512 void DialogPattern::UpdateFontScale()
1513 {
1514     auto dialogContext = GetDialogContext();
1515     CHECK_NULL_VOID(dialogContext);
1516     if (dialogContext->GetFontScale() != fontScaleForElderly_) {
1517         OnFontConfigurationUpdate();
1518         auto host = GetHost();
1519         CHECK_NULL_VOID(host);
1520         host->MarkModifyDone();
1521         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1522         fontScaleForElderly_ = dialogContext->GetFontScale();
1523     }
1524 }
1525 
SetButtonEnabled(const RefPtr<FrameNode> & buttonNode,bool enabled)1526 void DialogPattern::SetButtonEnabled(const RefPtr<FrameNode>& buttonNode, bool enabled)
1527 {
1528     // set Enabled and Focusable
1529     auto buttonButtonEvent = buttonNode->GetEventHub<ButtonEventHub>();
1530     CHECK_NULL_VOID(buttonButtonEvent);
1531     buttonButtonEvent->SetEnabled(enabled);
1532     buttonNode->GetOrCreateFocusHub()->SetFocusable(enabled);
1533 }
1534 
UpdateWrapperBackgroundStyle(const RefPtr<FrameNode> & host,const RefPtr<DialogTheme> & dialogTheme)1535 void DialogPattern::UpdateWrapperBackgroundStyle(const RefPtr<FrameNode>& host, const RefPtr<DialogTheme>& dialogTheme)
1536 {
1537     auto col = DynamicCast<FrameNode>(host->GetChildAtIndex(START_CHILD_INDEX));
1538     CHECK_NULL_VOID(col);
1539     auto colRenderContext = col->GetRenderContext();
1540     CHECK_NULL_VOID(colRenderContext);
1541     if (!dialogProperties_.customStyle && !dialogProperties_.backgroundColor.has_value() &&
1542         (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) || !colRenderContext->IsUniRenderEnabled() ||
1543             !dialogProperties_.isSysBlurStyle)) {
1544         colRenderContext->UpdateBackgroundColor(dialogTheme->GetBackgroundColor());
1545     }
1546     if (colRenderContext->GetBackBlurStyle().has_value()) {
1547         colRenderContext->UpdateBackBlurStyle(colRenderContext->GetBackBlurStyle());
1548     }
1549 }
1550 
DumpInfo()1551 void DialogPattern::DumpInfo()
1552 {
1553     DumpLog::GetInstance().AddDesc("Type: " + DialogTypeUtils::ConvertDialogTypeToString(dialogProperties_.type));
1554     if (!dialogProperties_.title.empty()) {
1555         DumpLog::GetInstance().AddDesc("Title: " + dialogProperties_.title);
1556     }
1557     if (!dialogProperties_.subtitle.empty()) {
1558         DumpLog::GetInstance().AddDesc("Subtitle: " + dialogProperties_.subtitle);
1559     }
1560     if (!dialogProperties_.content.empty()) {
1561         DumpLog::GetInstance().AddDesc("Content: " + dialogProperties_.content);
1562     }
1563     DumpLog::GetInstance().AddDesc(
1564         "DialogButtonDirection: " +
1565         DialogButtonDirectionUtils::ConvertDialogButtonDirectionToString(dialogProperties_.buttonDirection));
1566     if (dialogProperties_.width.has_value()) {
1567         DumpLog::GetInstance().AddDesc("Width: " + dialogProperties_.width.value().ToString());
1568     }
1569     if (dialogProperties_.height.has_value()) {
1570         DumpLog::GetInstance().AddDesc("Height: " + dialogProperties_.height.value().ToString());
1571     }
1572     if (dialogProperties_.backgroundBlurStyle.has_value()) {
1573         DumpLog::GetInstance().AddDesc(
1574             "BackgroundBlurStyle: " + std::to_string(dialogProperties_.backgroundBlurStyle.value()));
1575     }
1576     if (dialogProperties_.borderWidth.has_value()) {
1577         DumpLog::GetInstance().AddDesc("BorderWidth: " + dialogProperties_.borderWidth.value().ToString());
1578     }
1579     if (dialogProperties_.borderColor.has_value()) {
1580         DumpLog::GetInstance().AddDesc("BorderColor: " + dialogProperties_.borderColor.value().ToString());
1581     }
1582     if (dialogProperties_.backgroundColor.has_value()) {
1583         DumpLog::GetInstance().AddDesc("BackgroundColor: " + dialogProperties_.backgroundColor.value().ToString());
1584     }
1585     if (dialogProperties_.borderRadius.has_value()) {
1586         DumpLog::GetInstance().AddDesc("BorderRadius: " + dialogProperties_.borderRadius.value().ToString());
1587     }
1588     DumpBoolProperty();
1589     DumpObjectProperty();
1590 }
1591 
DumpBoolProperty()1592 void DialogPattern::DumpBoolProperty()
1593 {
1594     DumpLog::GetInstance().AddDesc("AutoCancel: " + GetBoolStr(dialogProperties_.autoCancel));
1595     DumpLog::GetInstance().AddDesc("CustomStyle: " + GetBoolStr(dialogProperties_.customStyle));
1596     DumpLog::GetInstance().AddDesc("IsMenu: " + GetBoolStr(dialogProperties_.isMenu));
1597     DumpLog::GetInstance().AddDesc("IsMask: " + GetBoolStr(dialogProperties_.isMask));
1598     DumpLog::GetInstance().AddDesc("IsModal: " + GetBoolStr(dialogProperties_.isModal));
1599     DumpLog::GetInstance().AddDesc("IsScenceBoardDialog: " + GetBoolStr(dialogProperties_.isScenceBoardDialog));
1600     DumpLog::GetInstance().AddDesc("IsSysBlurStyle: " + GetBoolStr(dialogProperties_.isSysBlurStyle));
1601     DumpLog::GetInstance().AddDesc("IsShowInSubWindow: " + GetBoolStr(dialogProperties_.isShowInSubWindow));
1602 }
1603 
DumpObjectProperty()1604 void DialogPattern::DumpObjectProperty()
1605 {
1606     DumpLog::GetInstance().AddDesc(
1607         "Alignment: " + DialogAlignmentUtils::ConvertDialogAlignmentToString(dialogProperties_.alignment));
1608     DumpLog::GetInstance().AddDesc("Offset: { dx: " + dialogProperties_.offset.GetX().ToString() +
1609                                    " dy: " + dialogProperties_.offset.GetY().ToString() + " }");
1610     if (dialogProperties_.buttons.size() > 0) {
1611         std::stringstream butonInfoSteam;
1612         butonInfoSteam << "Buttons: [";
1613         for (auto buttonInfo : dialogProperties_.buttons) {
1614             butonInfoSteam << "{ text: " << buttonInfo.text << " , color: " << buttonInfo.textColor << " }, ";
1615         }
1616         butonInfoSteam << "]";
1617         DumpLog::GetInstance().AddDesc(butonInfoSteam.str());
1618     }
1619     if (dialogProperties_.shadow.has_value()) {
1620         auto shadow = dialogProperties_.shadow.value();
1621         std::stringstream butonInfoSteam;
1622         static const int32_t precision = 2;
1623         butonInfoSteam << "Shadow: {";
1624         butonInfoSteam << " radius:" << std::fixed << std::setprecision(precision) << shadow.GetBlurRadius();
1625         butonInfoSteam << " style:" << std::to_string(static_cast<int32_t>(shadow.GetStyle()));
1626         butonInfoSteam << " type:" << std::to_string(static_cast<int32_t>(shadow.GetShadowType()));
1627         butonInfoSteam << " fill:" << GetBoolStr(shadow.GetIsFilled());
1628         butonInfoSteam << " offset:" << shadow.GetOffset().ToString();
1629         butonInfoSteam << " }";
1630         DumpLog::GetInstance().AddDesc(butonInfoSteam.str());
1631     }
1632     if (dialogProperties_.maskColor.has_value()) {
1633         DumpLog::GetInstance().AddDesc("MaskColor: " + dialogProperties_.maskColor.value().ToString());
1634     }
1635     if (dialogProperties_.maskRect.has_value()) {
1636         DumpLog::GetInstance().AddDesc("MaskRect: " + dialogProperties_.maskRect.value().ToString());
1637     }
1638 }
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1639 void DialogPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1640 {
1641     if (isFoldStatusChanged_ || type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::RESIZE) {
1642         auto host = GetHost();
1643         CHECK_NULL_VOID(host);
1644         InitHostWindowRect();
1645         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1646         isFoldStatusChanged_ = false;
1647     }
1648 }
1649 
InitHostWindowRect()1650 void DialogPattern::InitHostWindowRect()
1651 {
1652     if (!dialogProperties_.isShowInSubWindow) {
1653         isUIExtensionSubWindow_ = false;
1654         hostWindowRect_.Reset();
1655         return;
1656     }
1657 
1658     auto currentId = Container::CurrentId();
1659     auto container = Container::Current();
1660     CHECK_NULL_VOID(container);
1661     if (container->IsSubContainer()) {
1662         currentId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
1663         container = AceEngine::Get().GetContainer(currentId);
1664         CHECK_NULL_VOID(container);
1665     }
1666 
1667     if (container->IsUIExtensionWindow()) {
1668         isUIExtensionSubWindow_ = true;
1669         auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentId);
1670         CHECK_NULL_VOID(subwindow);
1671         auto rect = subwindow->GetUIExtensionHostWindowRect();
1672         hostWindowRect_ = RectF(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1673     }
1674 }
1675 
IsShowInFreeMultiWindow()1676 bool DialogPattern::IsShowInFreeMultiWindow()
1677 {
1678     auto currentId = Container::CurrentId();
1679     auto container = Container::Current();
1680     if (!container) {
1681         TAG_LOGW(AceLogTag::ACE_DIALOG, "container is null");
1682         return false;
1683     }
1684     if (container->IsSubContainer()) {
1685         currentId = SubwindowManager::GetInstance()->GetParentContainerId(currentId);
1686         container = AceEngine::Get().GetContainer(currentId);
1687         if (!container) {
1688             TAG_LOGW(AceLogTag::ACE_DIALOG, "parent container is null");
1689             return false;
1690         }
1691     }
1692     return container->IsFreeMultiWindow();
1693 }
1694 
DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)1695 void DialogPattern::DumpSimplifyInfo(std::unique_ptr<JsonValue>& json)
1696 {
1697     json->Put("Type", DialogTypeUtils::ConvertDialogTypeToString(dialogProperties_.type).c_str());
1698     if (!dialogProperties_.title.empty()) {
1699         json->Put("Title", dialogProperties_.title.c_str());
1700     }
1701     if (!dialogProperties_.subtitle.empty()) {
1702         json->Put("Subtitle", dialogProperties_.subtitle.c_str());
1703     }
1704     if (!dialogProperties_.content.empty()) {
1705         json->Put("Content", dialogProperties_.content.c_str());
1706     }
1707     if (dialogProperties_.buttonDirection != DialogButtonDirection::AUTO) {
1708         json->Put("ButtonDirection",
1709             DialogButtonDirectionUtils::ConvertDialogButtonDirectionToString(
1710                 dialogProperties_.buttonDirection).c_str());
1711     }
1712     if (dialogProperties_.backgroundBlurStyle.has_value() && dialogProperties_.backgroundBlurStyle.value() != 0) {
1713         json->Put("BackgroundBlurStyle", std::to_string(dialogProperties_.backgroundBlurStyle.value()).c_str());
1714     }
1715     if (dialogProperties_.backgroundColor.value_or(Color::TRANSPARENT) != Color::TRANSPARENT) {
1716         json->Put("BackgroundColor", dialogProperties_.backgroundColor.value_or(Color::TRANSPARENT).ToString().c_str());
1717     }
1718     DumpSimplifySizeProperty(json);
1719     DumpSimplifyBorderProperty(json);
1720     DumpSimplifyBoolProperty(json);
1721     DumpSimplifyObjectProperty(json);
1722 }
1723 
DumpSimplifyBorderProperty(std::unique_ptr<JsonValue> & json)1724 void DialogPattern::DumpSimplifyBorderProperty(std::unique_ptr<JsonValue>& json)
1725 {
1726     if (dialogProperties_.borderWidth.has_value()) {
1727         auto border = dialogProperties_.borderWidth.value();
1728         DimensionUnit unit = border.leftDimen.value_or(
1729             border.topDimen.value_or(border.rightDimen.value_or(border.bottomDimen.value_or(Dimension())))).Unit();
1730         Dimension defaultValue(0, unit);
1731         BorderWidthProperty defaultBorder = { defaultValue, defaultValue, defaultValue, defaultValue };
1732         if (!(border == defaultBorder)) {
1733             json->Put("BorderWidth", border.ToString().c_str());
1734         }
1735     }
1736     if (dialogProperties_.borderColor.has_value()) {
1737         auto color = dialogProperties_.borderColor.value();
1738         BorderColorProperty defaultValue = { Color::BLACK, Color::BLACK, Color::BLACK, Color::BLACK };
1739         if (!(color == defaultValue)) {
1740             json->Put("BorderColor", color.ToString().c_str());
1741         }
1742     }
1743     if (dialogProperties_.borderRadius.has_value()) {
1744         auto radius = dialogProperties_.borderRadius.value();
1745         DimensionUnit unit = radius.radiusTopLeft.value_or(radius.radiusTopRight.value_or(
1746             radius.radiusTopLeft.value_or(radius.radiusBottomLeft.value_or(
1747                 radius.radiusBottomRight.value_or(radius.radiusTopStart.value_or(radius.radiusTopEnd.value_or(
1748                     radius.radiusBottomStart.value_or(radius.radiusBottomEnd.value_or(Dimension()))))))))).Unit();
1749         Dimension defaultValue(0, unit);
1750         BorderRadiusProperty defaultRadius(defaultValue);
1751         if (!(radius == defaultRadius)) {
1752             json->Put("BorderRadius", dialogProperties_.borderRadius.value().ToString().c_str());
1753         }
1754     }
1755 }
1756 
DumpSimplifySizeProperty(std::unique_ptr<JsonValue> & json)1757 void DialogPattern::DumpSimplifySizeProperty(std::unique_ptr<JsonValue>& json)
1758 {
1759     if (dialogProperties_.width.has_value() || dialogProperties_.height.has_value()) {
1760         DimensionUnit unit = dialogProperties_.width.has_value() ?
1761             dialogProperties_.width.value().Unit() : dialogProperties_.height.value().Unit();
1762         CalcDimension defaultCalcDimen(0, unit);
1763         if (dialogProperties_.width.value_or(defaultCalcDimen) != defaultCalcDimen &&
1764             dialogProperties_.height.value_or(defaultCalcDimen) != defaultCalcDimen) {
1765             json->Put("Width", dialogProperties_.width.value_or(defaultCalcDimen).ToString().c_str());
1766             json->Put("Height", dialogProperties_.height.value_or(defaultCalcDimen).ToString().c_str());
1767         }
1768     }
1769 }
1770 
DumpSimplifyBoolProperty(std::unique_ptr<JsonValue> & json)1771 void DialogPattern::DumpSimplifyBoolProperty(std::unique_ptr<JsonValue>& json)
1772 {
1773     if (dialogProperties_.autoCancel) {
1774         json->Put("AutoCancel", GetBoolStr(dialogProperties_.autoCancel).c_str());
1775     }
1776     if (dialogProperties_.customStyle) {
1777         json->Put("CustomStyle", GetBoolStr(dialogProperties_.customStyle).c_str());
1778     }
1779     if (dialogProperties_.isMenu) {
1780         json->Put("IsMenu", GetBoolStr(dialogProperties_.isMenu).c_str());
1781     }
1782     if (dialogProperties_.isMask) {
1783         json->Put("IsMask", GetBoolStr(dialogProperties_.isMask).c_str());
1784     }
1785     if (dialogProperties_.isModal) {
1786         json->Put("IsModal", GetBoolStr(dialogProperties_.isModal).c_str());
1787     }
1788     if (dialogProperties_.isScenceBoardDialog) {
1789         json->Put("IsScenceBoardDialog", GetBoolStr(dialogProperties_.isScenceBoardDialog).c_str());
1790     }
1791     if (dialogProperties_.isSysBlurStyle) {
1792         json->Put("IsSysBlurStyle", GetBoolStr(dialogProperties_.isSysBlurStyle).c_str());
1793     }
1794     if (dialogProperties_.isShowInSubWindow) {
1795         json->Put("IsShowInSubWindow", GetBoolStr(dialogProperties_.isShowInSubWindow).c_str());
1796     }
1797 }
1798 
DumpSimplifyObjectProperty(std::unique_ptr<JsonValue> & json)1799 void DialogPattern::DumpSimplifyObjectProperty(std::unique_ptr<JsonValue>& json)
1800 {
1801     json->Put("Alignment", DialogAlignmentUtils::ConvertDialogAlignmentToString(dialogProperties_.alignment).c_str());
1802     std::stringstream stream;
1803     stream << dialogProperties_.offset.GetX().ToString() << "," << dialogProperties_.offset.GetY().ToString();
1804     json->Put("Offset", stream.str().c_str());
1805     if (!dialogProperties_.buttons.empty()) {
1806         std::unique_ptr<JsonValue> buttons = JsonUtil::Create(true);
1807         int32_t index = -1;
1808         for (const auto& buttonInfo : dialogProperties_.buttons) {
1809             std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
1810             child->Put("Text", buttonInfo.text.c_str());
1811             child->Put("Color", buttonInfo.textColor.c_str());
1812             index++;
1813             std::string key = "Button" + std::to_string(index);
1814             buttons->PutRef(key.c_str(), std::move(child));
1815         }
1816         json->PutRef("Buttons", std::move(buttons));
1817     }
1818     if (dialogProperties_.shadow.has_value()) {
1819         auto shadow = dialogProperties_.shadow.value();
1820         std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
1821 
1822         child->Put("Radius", shadow.GetBlurRadius());
1823         child->Put("Style", static_cast<int32_t>(shadow.GetStyle()));
1824         child->Put("Type", static_cast<int32_t>(shadow.GetShadowType()));
1825         child->Put("Fill", GetBoolStr(shadow.GetIsFilled()).c_str());
1826         child->Put("Offset", shadow.GetOffset().ToString().c_str());
1827         json->PutRef("Shadow", std::move(child));
1828     }
1829     if (dialogProperties_.maskColor.has_value()) {
1830         json->Put("MaskColor", dialogProperties_.maskColor.value().ToString().c_str());
1831     }
1832     if (dialogProperties_.maskRect.has_value()) {
1833         json->Put("MaskRect", dialogProperties_.maskRect.value().ToString().c_str());
1834     }
1835 }
1836 
GetEmbeddedOverlay(const RefPtr<OverlayManager> & context)1837 RefPtr<OverlayManager> DialogPattern::GetEmbeddedOverlay(const RefPtr<OverlayManager>& context)
1838 {
1839     auto host = GetHost();
1840     auto overlayManager = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(host);
1841     CHECK_NULL_RETURN(overlayManager, context);
1842     return overlayManager;
1843 }
1844 
OnAttachToMainTree()1845 void DialogPattern::OnAttachToMainTree()
1846 {
1847     auto host = GetHost();
1848     CHECK_NULL_VOID(host);
1849     auto parentNode = AceType::DynamicCast<FrameNode>(host->GetParent());
1850     CHECK_NULL_VOID(parentNode);
1851     if (parentNode->GetTag() != V2::NAVDESTINATION_VIEW_ETS_TAG) {
1852         return;
1853     }
1854     auto dialogRenderContext = host->GetRenderContext();
1855     CHECK_NULL_VOID(dialogRenderContext);
1856     auto navDestinationPattern = parentNode->GetPattern<NavDestinationPattern>();
1857     CHECK_NULL_VOID(navDestinationPattern);
1858     auto zIndex = navDestinationPattern->GetTitlebarZIndex();
1859     dialogRenderContext->UpdateZIndex(zIndex + 1);
1860 }
1861 
GetOverlayManager(const RefPtr<FrameNode> & host)1862 RefPtr<OverlayManager> DialogPattern::GetOverlayManager(const RefPtr<FrameNode>& host)
1863 {
1864     RefPtr<PipelineContext> pipeline;
1865     if (host) {
1866         pipeline = host->GetContext();
1867     } else {
1868         pipeline = PipelineContext::GetCurrentContext();
1869     }
1870     CHECK_NULL_RETURN(pipeline, nullptr);
1871     auto overlayManager = pipeline->GetOverlayManager();
1872     CHECK_NULL_RETURN(overlayManager, nullptr);
1873     return GetEmbeddedOverlay(overlayManager);
1874 }
1875 
OverlayDismissDialog(const RefPtr<FrameNode> & dialogNode)1876 void DialogPattern::OverlayDismissDialog(const RefPtr<FrameNode>& dialogNode)
1877 {
1878     auto overlayManager = GetOverlayManager(nullptr);
1879     CHECK_NULL_VOID(overlayManager);
1880     overlayManager->RemoveDialog(dialogNode, false);
1881     if (overlayManager->isMaskNode(GetHost()->GetId())) {
1882         overlayManager->PopModalDialog(GetHost()->GetId());
1883     }
1884 }
1885 } // namespace OHOS::Ace::NG
1886