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