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