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