• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
16 
17 #include <climits>
18 #include <cstdint>
19 #include <cstring>
20 #include <optional>
21 #include <string>
22 
23 #include "base/geometry/dimension.h"
24 #include "base/json/json_util.h"
25 #include "base/log/log.h"
26 #include "base/memory/ace_type.h"
27 #include "base/memory/referenced.h"
28 #include "base/subwindow/subwindow_manager.h"
29 #include "base/utils/utils.h"
30 #include "bridge/common/dom/dom_type.h"
31 #include "core/common/ace_engine.h"
32 #include "core/common/container.h"
33 #include "core/common/recorder/event_recorder.h"
34 #include "core/components/button/button_theme.h"
35 #include "core/components/common/properties/alignment.h"
36 #include "core/components/theme/icon_theme.h"
37 #include "core/components_ng/base/frame_node.h"
38 #include "core/components_ng/base/ui_node.h"
39 #include "core/components_ng/base/view_stack_processor.h"
40 #include "core/components_ng/event/gesture_event_hub.h"
41 #include "core/components_ng/layout/layout_property.h"
42 #include "core/components_ng/pattern/button/button_layout_property.h"
43 #include "core/components_ng/pattern/button/button_pattern.h"
44 #include "core/components_ng/pattern/divider/divider_layout_property.h"
45 #include "core/components_ng/pattern/divider/divider_model_ng.h"
46 #include "core/components_ng/pattern/divider/divider_pattern.h"
47 #include "core/components_ng/pattern/flex/flex_layout_algorithm.h"
48 #include "core/components_ng/pattern/flex/flex_layout_property.h"
49 #include "core/components_ng/pattern/image/image_pattern.h"
50 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
51 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
52 #include "core/components_ng/pattern/list/list_pattern.h"
53 #include "core/components_ng/pattern/overlay/overlay_manager.h"
54 #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h"
55 #include "core/components_ng/pattern/relative_container/relative_container_pattern.h"
56 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
57 #include "core/components_ng/pattern/text/text_layout_property.h"
58 #include "core/components_ng/pattern/text/text_pattern.h"
59 #include "core/components_ng/property/calc_length.h"
60 #include "core/components_ng/property/measure_property.h"
61 #include "core/components_v2/inspector/inspector_constants.h"
62 #include "core/event/key_event.h"
63 #include "core/event/touch_event.h"
64 #include "core/pipeline/base/element_register.h"
65 #include "core/pipeline_ng/pipeline_context.h"
66 
67 namespace OHOS::Ace::NG {
68 
69 namespace {
70 constexpr int32_t SHEET_INFO_IDX = -2;
71 constexpr Dimension SHEET_IMAGE_MARGIN = 16.0_vp;
72 constexpr Dimension SHEET_DIVIDER_WIDTH = 1.0_px;
73 constexpr Dimension SHEET_LIST_PADDING = 24.0_vp;
74 constexpr Dimension DIALOG_BUTTON_TEXT_SIZE = 16.0_fp;
75 constexpr Color DEFAULT_BUTTON_COLOR = Color(0xff007dff);
76 const CalcLength SHEET_IMAGE_SIZE(40.0_vp);
77 constexpr int32_t TWO_BUTTON_MODE = 2;
78 constexpr int32_t ONE_BUTTON_MODE = 1;
79 constexpr int32_t START_CHILD_INDEX = 0;
80 constexpr uint32_t DIALOG_TITLE_MAXLINES = 1;
81 constexpr Dimension DIALOG_ONE_TITLE_ALL_HEIGHT = 56.0_vp;
82 constexpr Dimension DIALOG_TITLE_CONTENT_HEIGHT = 35.0_px;
83 constexpr int32_t DIALOG_TITLE_AVE_BY_2 = 2;
84 constexpr Dimension DIALOG_CONTENT_PADDING_TOP = 0.0_vp;
85 constexpr Dimension DIALOG_SUBTITLE_PADDING_LEFT = 24.0_vp;
86 constexpr Dimension DIALOG_SUBTITLE_PADDING_RIGHT = 24.0_vp;
87 constexpr Dimension DIALOG_TWO_TITLE_ZERO_SPACE = 0.0_vp;
88 constexpr Dimension DIALOG_TWO_TITLE_SPACE = 16.0_vp;
89 constexpr Dimension ADAPT_TITLE_MIN_FONT_SIZE = 16.0_fp;
90 constexpr Dimension ADAPT_SUBTITLE_MIN_FONT_SIZE = 12.0_fp;
91 constexpr uint32_t ADAPT_TITLE_MAX_LINES = 2;
92 } // namespace
93 
OnModifyDone()94 void DialogPattern::OnModifyDone()
95 {
96     Pattern::OnModifyDone();
97     auto host = GetHost();
98     CHECK_NULL_VOID(host);
99     auto gestureHub = host->GetOrCreateGestureEventHub();
100     CHECK_NULL_VOID(gestureHub);
101 
102     if (!onClick_) {
103         InitClickEvent(gestureHub);
104     }
105     auto focusHub = host->GetOrCreateFocusHub();
106     CHECK_NULL_VOID(focusHub);
107     RegisterOnKeyEvent(focusHub);
108 }
109 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)110 void DialogPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
111 {
112     GestureEventFunc task = [weak = WeakClaim(this)](const GestureEvent& info) {
113         auto pattern = weak.Upgrade();
114         CHECK_NULL_VOID(pattern);
115         pattern->HandleClick(info);
116     };
117     onClick_ = MakeRefPtr<ClickEvent>(std::move(task));
118     gestureHub->AddClickEvent(onClick_);
119 }
120 
HandleClick(const GestureEvent & info)121 void DialogPattern::HandleClick(const GestureEvent& info)
122 {
123     if (info.GetSourceDevice() == SourceType::KEYBOARD) {
124         return;
125     }
126     auto host = GetHost();
127     CHECK_NULL_VOID(host);
128     auto props = host->GetLayoutProperty<DialogLayoutProperty>();
129     CHECK_NULL_VOID(props);
130     auto globalOffset = host->GetPaintRectOffset();
131     auto autoCancel = props->GetAutoCancel().value_or(true);
132     if (autoCancel) {
133         auto content = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
134         CHECK_NULL_VOID(content);
135         auto contentRect = content->GetGeometryNode()->GetFrameRect();
136         // close dialog if clicked outside content rect
137         auto&& clickPosition = info.GetGlobalLocation();
138         if (!contentRect.IsInRegion(
139                 PointF(clickPosition.GetX() - globalOffset.GetX(), clickPosition.GetY() - globalOffset.GetY()))) {
140             PopDialog(-1);
141             auto pipeline = PipelineContext::GetCurrentContext();
142             CHECK_NULL_VOID(pipeline);
143             auto overlayManager = pipeline->GetOverlayManager();
144             CHECK_NULL_VOID(overlayManager);
145             if (overlayManager->isMaskNode(GetHost()->GetId())) {
146                 overlayManager->PopModalDialog(GetHost()->GetId());
147             }
148         }
149     }
150 }
151 
PopDialog(int32_t buttonIdx=-1)152 void DialogPattern::PopDialog(int32_t buttonIdx = -1)
153 {
154     auto pipeline = PipelineContext::GetCurrentContext();
155     CHECK_NULL_VOID(pipeline);
156     auto overlayManager = pipeline->GetOverlayManager();
157     CHECK_NULL_VOID(overlayManager);
158     auto host = GetHost();
159     CHECK_NULL_VOID(host);
160     if (host->IsRemoving()) {
161         return;
162     }
163 
164     auto hub = host->GetEventHub<DialogEventHub>();
165     if (buttonIdx != -1) {
166         hub->FireSuccessEvent(buttonIdx);
167         RecordEvent(buttonIdx);
168     } else {
169         // trigger onCancel callback
170         hub->FireCancelEvent();
171         RecordEvent(buttonIdx);
172     }
173     if (dialogProperties_.isShowInSubWindow) {
174         SubwindowManager::GetInstance()->DeleteHotAreas(
175             SubwindowManager::GetInstance()->GetDialogSubWindowId(), host->GetId());
176         SubwindowManager::GetInstance()->HideDialogSubWindow(SubwindowManager::GetInstance()->GetDialogSubWindowId());
177     }
178     overlayManager->CloseDialog(host);
179 }
180 
RecordEvent(int32_t btnIndex) const181 void DialogPattern::RecordEvent(int32_t btnIndex) const
182 {
183     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
184         return;
185     }
186     std::string btnText;
187     if (btnIndex >= 0 && static_cast<size_t>(btnIndex) < dialogProperties_.buttons.size()) {
188         btnText = dialogProperties_.buttons.at(btnIndex).text;
189     }
190     Recorder::EventType eventType;
191     if (btnIndex == -1) {
192         eventType = Recorder::EventType::DIALOG_CANCEL;
193     } else {
194         eventType = Recorder::EventType::DIALOG_ACTION;
195     }
196     Recorder::EventParamsBuilder builder;
197     builder.SetEventType(eventType)
198         .SetText(btnText)
199         .SetExtra(Recorder::KEY_TITLE, title_)
200         .SetExtra(Recorder::KEY_SUB_TITLE, subtitle_);
201     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
202 }
203 
204 // set render context properties of content frame
UpdateContentRenderContext(const RefPtr<FrameNode> & contentNode,const DialogProperties & props)205 void DialogPattern::UpdateContentRenderContext(const RefPtr<FrameNode>& contentNode, const DialogProperties& props)
206 {
207     auto contentRenderContext = contentNode->GetRenderContext();
208     CHECK_NULL_VOID(contentRenderContext);
209     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
210         contentRenderContext->IsUniRenderEnabled() && props.isSysBlurStyle) {
211         BlurStyleOption styleOption;
212         styleOption.blurStyle = static_cast<BlurStyle>(
213             props.backgroundBlurStyle.value_or(static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)));
214         contentRenderContext->UpdateBackBlurStyle(styleOption);
215         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(Color::TRANSPARENT));
216     } else {
217         contentRenderContext->UpdateBackgroundColor(props.backgroundColor.value_or(dialogTheme_->GetBackgroundColor()));
218     }
219 
220     if (props.borderRadius.has_value()) {
221         contentRenderContext->UpdateBorderRadius(props.borderRadius.value());
222     } else {
223         BorderRadiusProperty radius;
224         radius.SetRadius(dialogTheme_->GetRadius().GetX());
225         contentRenderContext->UpdateBorderRadius(radius);
226     }
227     contentRenderContext->SetClipToBounds(true);
228 }
229 
CreateDialogScroll(const DialogProperties & dialogProps)230 RefPtr<FrameNode> DialogPattern::CreateDialogScroll(const DialogProperties& dialogProps)
231 {
232     auto scroll = FrameNode::CreateFrameNode(
233         V2::SCROLL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ScrollPattern>());
234     CHECK_NULL_RETURN(scroll, nullptr);
235     auto props = scroll->GetLayoutProperty<ScrollLayoutProperty>();
236     props->UpdateAxis(Axis::VERTICAL);
237     props->UpdateAlignment(Alignment::CENTER_LEFT);
238     // If title not exist, set scroll align center so that text align center.
239     if ((dialogProps.title.empty() && dialogProps.subtitle.empty()) ||
240         SystemProperties::GetDeviceType() == DeviceType::WATCH) {
241         props->UpdateAlignSelf(FlexAlign::CENTER);
242     } else {
243         props->UpdateAlignSelf(FlexAlign::FLEX_START);
244     }
245     return scroll;
246 }
247 
BuildChild(const DialogProperties & props)248 void DialogPattern::BuildChild(const DialogProperties& props)
249 {
250     // append customNode
251     auto customNode = customNode_.Upgrade();
252     if (customNode) {
253         // wrap custom node to set background color and round corner
254         auto contentWrapper = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
255             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
256         CHECK_NULL_VOID(contentWrapper);
257         if (!props.customStyle) {
258             UpdateContentRenderContext(contentWrapper, props);
259         }
260         customNode->MountToParent(contentWrapper);
261         auto dialog = GetHost();
262         contentWrapper->MountToParent(dialog);
263         return;
264     }
265 
266     // Make dialog Content Column
267     auto contentColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
268         AceType::MakeRefPtr<LinearLayoutPattern>(true));
269     CHECK_NULL_VOID(contentColumn);
270 
271     if (!props.title.empty() || !props.subtitle.empty()) {
272         auto title = BuildTitle(props);
273         CHECK_NULL_VOID(title);
274         contentColumn->AddChild(title);
275     }
276 
277     if (!props.content.empty()) {
278         auto content = BuildContent(props);
279         CHECK_NULL_VOID(content);
280         // create a scroll
281         auto scroll = CreateDialogScroll(props);
282         CHECK_NULL_VOID(scroll);
283         content->MountToParent(scroll);
284         scroll->MountToParent(contentColumn);
285         scroll->MarkModifyDone();
286     }
287 
288     if (!props.customStyle) {
289         UpdateContentRenderContext(contentColumn, props);
290     }
291 
292     auto columnProp = AceType::DynamicCast<LinearLayoutProperty>(contentColumn->GetLayoutProperty());
293     CHECK_NULL_VOID(columnProp);
294     // content is full screen in Watch mode
295     auto deviceType = SystemProperties::GetDeviceType();
296     if (deviceType == DeviceType::WATCH) {
297         columnProp->UpdateMeasureType(MeasureType::MATCH_PARENT);
298     } else {
299         columnProp->UpdateMeasureType(MeasureType::MATCH_CONTENT);
300     }
301 
302     // build ActionSheet child
303     if (props.type == DialogType::ACTION_SHEET && !props.sheetsInfo.empty()) {
304         auto sheetContainer = BuildSheet(props.sheetsInfo);
305         CHECK_NULL_VOID(sheetContainer);
306         sheetContainer->MountToParent(contentColumn);
307         // scrollable
308         sheetContainer->MarkModifyDone();
309     }
310 
311     // Make Menu node if hasMenu (actionMenu)
312     if (props.isMenu) {
313         bool hasTitle = !props.title.empty() || !props.subtitle.empty();
314         auto menu = BuildMenu(props.buttons, hasTitle);
315         CHECK_NULL_VOID(menu);
316         menu->MountToParent(contentColumn);
317     } else {
318         // build buttons
319         if (!props.buttons.empty()) {
320             auto buttonContainer = BuildButtons(props.buttons, props.buttonDirection);
321             CHECK_NULL_VOID(buttonContainer);
322             buttonContainer->MountToParent(contentColumn);
323         }
324     }
325 
326     auto dialog = GetHost();
327     contentColumn->MountToParent(dialog);
328 }
329 
BuildMainTitle(const DialogProperties & dialogProperties)330 RefPtr<FrameNode> DialogPattern::BuildMainTitle(const DialogProperties& dialogProperties)
331 {
332     auto title = FrameNode::CreateFrameNode(
333         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
334     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(title->GetLayoutProperty());
335     CHECK_NULL_RETURN(titleProp, nullptr);
336     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
337     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
338     std::string titleContent = dialogProperties.title.empty() ? dialogProperties.subtitle : dialogProperties.title;
339     titleProp->UpdateContent(titleContent);
340     auto titleStyle = dialogTheme_->GetTitleTextStyle();
341     titleProp->UpdateFontSize(titleStyle.GetFontSize());
342     titleProp->UpdateFontWeight(titleStyle.GetFontWeight());
343     titleProp->UpdateTextColor(titleStyle.GetTextColor());
344     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
345         titleProp->UpdateAdaptMaxFontSize(dialogTheme_->GetTitleTextStyle().GetFontSize());
346         titleProp->UpdateAdaptMinFontSize(ADAPT_TITLE_MIN_FONT_SIZE);
347         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
348         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
349     }
350     PaddingProperty titlePadding;
351     auto paddingInTheme = (dialogProperties.content.empty() && dialogProperties.buttons.empty())
352                               ? dialogTheme_->GetTitleDefaultPadding()
353                               : dialogTheme_->GetTitleAdjustPadding();
354     titlePadding.left = CalcLength(paddingInTheme.Left());
355     titlePadding.right = CalcLength(paddingInTheme.Right());
356     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
357         titlePadding.top = CalcLength(DIALOG_TWO_TITLE_SPACE);
358         titlePadding.bottom = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
359     } else {
360         titlePadding.top = CalcLength(
361             (DIALOG_ONE_TITLE_ALL_HEIGHT - Dimension(DIALOG_TITLE_CONTENT_HEIGHT.ConvertToVp(), DimensionUnit::VP)) /
362             DIALOG_TITLE_AVE_BY_2);
363         titlePadding.bottom = CalcLength(
364             (DIALOG_ONE_TITLE_ALL_HEIGHT - Dimension(DIALOG_TITLE_CONTENT_HEIGHT.ConvertToVp(), DimensionUnit::VP)) /
365             DIALOG_TITLE_AVE_BY_2);
366     }
367     titleProp->UpdatePadding(titlePadding);
368 
369     // XTS inspector value
370     title_ = dialogProperties.title;
371     subtitle_ = dialogProperties.subtitle;
372 
373     auto titleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
374         AceType::MakeRefPtr<LinearLayoutPattern>(false));
375     CHECK_NULL_RETURN(titleRow, nullptr);
376     auto titleRowProps = titleRow->GetLayoutProperty<LinearLayoutProperty>();
377     CHECK_NULL_RETURN(titleRowProps, nullptr);
378     titleRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
379     titleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
380     title->MountToParent(titleRow);
381     title->MarkModifyDone();
382     return titleRow;
383 }
384 
BuildSubTitle(const DialogProperties & dialogProperties)385 RefPtr<FrameNode> DialogPattern::BuildSubTitle(const DialogProperties& dialogProperties)
386 {
387     auto subtitle = FrameNode::CreateFrameNode(
388         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
389     auto titleProp = AceType::DynamicCast<TextLayoutProperty>(subtitle->GetLayoutProperty());
390     CHECK_NULL_RETURN(titleProp, nullptr);
391     auto titleStyle = dialogTheme_->GetSubTitleTextStyle();
392     titleProp->UpdateMaxLines(DIALOG_TITLE_MAXLINES);
393     titleProp->UpdateTextOverflow(TextOverflow::ELLIPSIS);
394     titleProp->UpdateContent(dialogProperties.subtitle);
395     titleProp->UpdateFontSize(titleStyle.GetFontSize());
396     titleProp->UpdateTextColor(titleStyle.GetTextColor());
397     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
398         titleProp->UpdateAdaptMaxFontSize(titleStyle.GetFontSize());
399         titleProp->UpdateAdaptMinFontSize(ADAPT_SUBTITLE_MIN_FONT_SIZE);
400         titleProp->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
401         titleProp->UpdateMaxLines(ADAPT_TITLE_MAX_LINES);
402     }
403     PaddingProperty titlePadding;
404     titlePadding.left = CalcLength(DIALOG_SUBTITLE_PADDING_LEFT);
405     titlePadding.right = CalcLength(DIALOG_SUBTITLE_PADDING_RIGHT);
406     titlePadding.top = CalcLength(DIALOG_TWO_TITLE_ZERO_SPACE);
407     titlePadding.bottom = CalcLength(DIALOG_TWO_TITLE_SPACE);
408     titleProp->UpdatePadding(titlePadding);
409 
410     // XTS inspector value
411     subtitle_ = dialogProperties.subtitle;
412 
413     auto subtitleRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
414         AceType::MakeRefPtr<LinearLayoutPattern>(false));
415     CHECK_NULL_RETURN(subtitleRow, nullptr);
416     auto subtitleRowProps = subtitleRow->GetLayoutProperty<LinearLayoutProperty>();
417     CHECK_NULL_RETURN(subtitleRowProps, nullptr);
418     subtitleRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
419     subtitleRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
420     subtitle->MountToParent(subtitleRow);
421     subtitle->MarkModifyDone();
422     return subtitleRow;
423 }
424 
BuildTitle(const DialogProperties & dialogProperties)425 RefPtr<FrameNode> DialogPattern::BuildTitle(const DialogProperties& dialogProperties)
426 {
427     auto titleRow = BuildMainTitle(dialogProperties);
428     if (!dialogProperties.title.empty() && !dialogProperties.subtitle.empty()) {
429         auto titleColumn = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
430             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
431         CHECK_NULL_RETURN(titleColumn, nullptr);
432         auto columnProps = titleColumn->GetLayoutProperty<LinearLayoutProperty>();
433         CHECK_NULL_RETURN(columnProps, nullptr);
434         columnProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
435         columnProps->UpdateMeasureType(MeasureType::MATCH_CONTENT);
436         auto subtitleRow = BuildSubTitle(dialogProperties);
437         titleColumn->AddChild(titleRow);
438         titleColumn->AddChild(subtitleRow);
439         return titleColumn;
440     }
441     return titleRow;
442 }
443 
BuildContent(const DialogProperties & props)444 RefPtr<FrameNode> DialogPattern::BuildContent(const DialogProperties& props)
445 {
446     // Make Content node
447     auto contentNode = FrameNode::CreateFrameNode(
448         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
449     auto contentProp = AceType::DynamicCast<TextLayoutProperty>(contentNode->GetLayoutProperty());
450     CHECK_NULL_RETURN(contentProp, nullptr);
451     // textAlign always align start. When text line count 1 and title doesn't exist, set text center position.
452     contentProp->UpdateTextAlign(TextAlign::START);
453     contentProp->UpdateContent(props.content);
454     auto contentStyle = dialogTheme_->GetContentTextStyle();
455     contentProp->UpdateFontSize(contentStyle.GetFontSize());
456     contentProp->UpdateTextColor(contentStyle.GetTextColor());
457     // update padding
458     Edge contentPaddingInTheme;
459     PaddingProperty contentPadding;
460     if (!props.title.empty() || !props.subtitle.empty()) {
461         contentPaddingInTheme =
462             props.buttons.empty() ? dialogTheme_->GetDefaultPadding() : dialogTheme_->GetAdjustPadding();
463         contentPadding.top = CalcLength(DIALOG_CONTENT_PADDING_TOP);
464     } else {
465         contentPaddingInTheme =
466             props.buttons.empty() ? dialogTheme_->GetContentDefaultPadding() : dialogTheme_->GetContentAdjustPadding();
467         contentPadding.top = CalcLength(contentPaddingInTheme.Top());
468     }
469     contentPadding.left = CalcLength(contentPaddingInTheme.Left());
470     contentPadding.right = CalcLength(contentPaddingInTheme.Right());
471     contentPadding.bottom = CalcLength(contentPaddingInTheme.Bottom());
472     contentProp->UpdatePadding(contentPadding);
473 
474     // XTS inspector value
475     message_ = props.content;
476     contentNode->MarkModifyDone();
477     return contentNode;
478 }
479 
480 // to close dialog when clicked, use button index in Prompt to trigger success callback
BindCloseCallBack(const RefPtr<GestureEventHub> & hub,int32_t buttonIdx)481 void DialogPattern::BindCloseCallBack(const RefPtr<GestureEventHub>& hub, int32_t buttonIdx)
482 {
483     auto host = GetHost();
484     auto closeCallback = [weak = WeakClaim(RawPtr(host)), buttonIdx](GestureEvent& /*info*/) {
485         auto dialog = weak.Upgrade();
486         CHECK_NULL_VOID(dialog);
487         dialog->GetPattern<DialogPattern>()->PopDialog(buttonIdx);
488     };
489 
490     hub->AddClickEvent(AceType::MakeRefPtr<ClickEvent>(closeCallback));
491 }
492 
ParseButtonFontColorAndBgColor(const ButtonInfo & params,std::string & textColor,std::optional<Color> & bgColor)493 void DialogPattern::ParseButtonFontColorAndBgColor(
494     const ButtonInfo& params, std::string& textColor, std::optional<Color>& bgColor)
495 {
496     // Parse Button Style
497     if (params.dlgButtonStyle.has_value()) {
498         switch (params.dlgButtonStyle.value()) {
499             case DialogButtonStyle::DEFAULT:
500                 textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
501                 bgColor = dialogTheme_->GetButtonDefaultBgColor();
502                 break;
503             case DialogButtonStyle::HIGHTLIGHT:
504                 textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
505                 bgColor = dialogTheme_->GetButtonHighlightBgColor();
506                 break;
507             default:
508                 break;
509         }
510     }
511 
512     // font color and background color
513     if (!params.textColor.empty()) {
514         textColor = params.textColor;
515     }
516     if (params.isBgColorSetted) {
517         bgColor = params.bgColor;
518     }
519 
520     // Parse default focus
521     if (textColor.empty()) {
522         if (params.defaultFocus && isFirstDefaultFocus_) {
523             textColor = dialogTheme_->GetButtonHighlightFontColor().ColorToString();
524         } else {
525             textColor = dialogTheme_->GetButtonDefaultFontColor().ColorToString();
526         }
527     }
528     if (!bgColor.has_value()) {
529         if (params.defaultFocus && isFirstDefaultFocus_) {
530             bgColor = dialogTheme_->GetButtonHighlightBgColor();
531             isFirstDefaultFocus_ = false;
532         } else {
533             bgColor = dialogTheme_->GetButtonDefaultBgColor();
534         }
535     }
536 }
537 
CreateButton(const ButtonInfo & params,int32_t index,bool isCancel,bool isVertical,int32_t length)538 RefPtr<FrameNode> DialogPattern::CreateButton(
539     const ButtonInfo& params, int32_t index, bool isCancel, bool isVertical, int32_t length)
540 {
541     auto buttonNode = FrameNode::CreateFrameNode(
542         V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ButtonPattern>());
543     CHECK_NULL_RETURN(buttonNode, nullptr);
544     UpdateDialogButtonProperty(buttonNode, index, isVertical, length);
545 
546     // parse button text color and background color
547     std::string textColor;
548     std::optional<Color> bgColor;
549     ParseButtonFontColorAndBgColor(params, textColor, bgColor);
550 
551     // append text inside button
552     auto textNode = CreateButtonText(params.text, textColor);
553     CHECK_NULL_RETURN(textNode, nullptr);
554     textNode->MountToParent(buttonNode);
555     textNode->MarkModifyDone();
556 
557     SetButtonEnabled(buttonNode, params.enabled);
558 
559     auto hub = buttonNode->GetOrCreateGestureEventHub();
560     CHECK_NULL_RETURN(hub, nullptr);
561     // bind click event
562     if (params.action) {
563         hub->AddClickEvent(params.action);
564     }
565 
566     // to close dialog when clicked inside button rect
567     if (!isCancel) {
568         BindCloseCallBack(hub, index);
569     } else {
570         BindCloseCallBack(hub, -1);
571     }
572 
573     // add scale animation
574     auto inputHub = buttonNode->GetOrCreateInputEventHub();
575     CHECK_NULL_RETURN(inputHub, nullptr);
576     inputHub->SetHoverEffect(HoverEffectType::AUTO);
577 
578     // update background color
579     auto renderContext = buttonNode->GetRenderContext();
580     CHECK_NULL_RETURN(renderContext, nullptr);
581     renderContext->UpdateBackgroundColor(bgColor.value());
582 
583     // set button default height
584     auto layoutProps = buttonNode->GetLayoutProperty();
585     CHECK_NULL_RETURN(layoutProps, nullptr);
586     auto pipeline = PipelineContext::GetCurrentContext();
587     CHECK_NULL_RETURN(pipeline, nullptr);
588     auto theme = pipeline->GetTheme<ButtonTheme>();
589     CHECK_NULL_RETURN(theme, nullptr);
590     layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(theme->GetHeight())));
591 
592     return buttonNode;
593 }
594 
UpdateDialogButtonProperty(RefPtr<FrameNode> & buttonNode,int32_t index,bool isVertical,int32_t length)595 void DialogPattern::UpdateDialogButtonProperty(
596     RefPtr<FrameNode>& buttonNode, int32_t index, bool isVertical, int32_t length)
597 {
598     // update button padding
599     auto buttonProp = AceType::DynamicCast<ButtonLayoutProperty>(buttonNode->GetLayoutProperty());
600     PaddingProperty buttonPadding;
601     buttonPadding.left = CalcLength(SHEET_LIST_PADDING);
602     buttonPadding.right = CalcLength(SHEET_LIST_PADDING);
603     buttonProp->UpdatePadding(buttonPadding);
604 
605     if (!isVertical) {
606         // set flex grow to fill horizontal space
607         buttonProp->UpdateLayoutWeight(1);
608         buttonProp->UpdateFlexGrow(1.0);
609         buttonProp->UpdateFlexShrink(1.0);
610     } else if (isVertical && index != (length - 1)) {
611         // update button space in vertical
612         auto buttonSpace = dialogTheme_->GetMutiButtonPaddingVertical();
613         MarginProperty margin = {
614             .bottom = CalcLength(buttonSpace),
615         };
616         buttonProp->UpdateMargin(margin);
617     }
618 }
619 
CreateDivider(const Dimension & dividerLength,const Dimension & dividerWidth,const Color & color,const Dimension & space)620 RefPtr<FrameNode> DialogPattern::CreateDivider(
621     const Dimension& dividerLength, const Dimension& dividerWidth, const Color& color, const Dimension& space)
622 {
623     auto dividerNode = FrameNode::CreateFrameNode(
624         V2::DIVIDER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<DividerPattern>());
625     CHECK_NULL_RETURN(dividerNode, nullptr);
626     auto dividerProps = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
627     CHECK_NULL_RETURN(dividerProps, nullptr);
628     dividerProps->UpdateVertical(true);
629     dividerProps->UpdateStrokeWidth(dividerWidth);
630     dividerProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(dividerLength)));
631     auto dividerPaintProps = dividerNode->GetPaintProperty<DividerRenderProperty>();
632     CHECK_NULL_RETURN(dividerPaintProps, nullptr);
633     dividerPaintProps->UpdateDividerColor(color);
634 
635     // add divider margin
636     MarginProperty margin = {
637         .left = CalcLength((space - dividerWidth) / 2),
638         .right = CalcLength((space - dividerWidth) / 2),
639     };
640     dividerProps->UpdateMargin(margin);
641     return dividerNode;
642 }
643 
644 // alert dialog buttons
BuildButtons(const std::vector<ButtonInfo> & buttons,const DialogButtonDirection & direction)645 RefPtr<FrameNode> DialogPattern::BuildButtons(
646     const std::vector<ButtonInfo>& buttons, const DialogButtonDirection& direction)
647 {
648     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
649     RefPtr<FrameNode> container;
650     bool isVertical;
651     if (direction == DialogButtonDirection::HORIZONTAL ||
652         (direction == DialogButtonDirection::AUTO && buttons.size() == TWO_BUTTON_MODE)) {
653         // use horizontal layout
654         isVertical = false;
655         container = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(false));
656         CHECK_NULL_RETURN(container, nullptr);
657         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
658         layoutProps->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
659         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
660     } else {
661         // use vertical layout
662         isVertical = true;
663         container = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, Id, AceType::MakeRefPtr<LinearLayoutPattern>(true));
664         auto layoutProps = container->GetLayoutProperty<LinearLayoutProperty>();
665         layoutProps->UpdateCrossAxisAlign(FlexAlign::STRETCH);
666         layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
667     }
668     CHECK_NULL_RETURN(container, nullptr);
669     // set action's padding
670     PaddingProperty actionPadding;
671     if (buttons.size() == ONE_BUTTON_MODE || isVertical) {
672         actionPadding.left = CalcLength(dialogTheme_->GetSingleButtonPaddingStart());
673         actionPadding.right = CalcLength(dialogTheme_->GetSingleButtonPaddingEnd());
674     } else {
675         actionPadding.left = CalcLength(dialogTheme_->GetMutiButtonPaddingStart());
676         actionPadding.right = CalcLength(dialogTheme_->GetMutiButtonPaddingEnd());
677     }
678     auto padding = dialogTheme_->GetActionsPadding();
679     actionPadding.top = CalcLength(dialogTheme_->GetButtonWithContentPadding());
680     actionPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
681     container->GetLayoutProperty()->UpdatePadding(actionPadding);
682 
683     AddButtonAndDivider(buttons, container, isVertical);
684     container->MarkModifyDone();
685     buttonContainer_ = container;
686     return container;
687 }
688 
AddButtonAndDivider(const std::vector<ButtonInfo> & buttons,const RefPtr<NG::FrameNode> & container,bool isVertical)689 void DialogPattern::AddButtonAndDivider(
690     const std::vector<ButtonInfo>& buttons, const RefPtr<NG::FrameNode>& container, bool isVertical)
691 {
692     auto dividerLength = dialogTheme_->GetDividerLength();
693     auto dividerWidth = dialogTheme_->GetDividerBetweenButtonWidth_();
694     auto dividerColor = dialogTheme_->GetDividerColor();
695     auto buttonSpace = dialogTheme_->GetMutiButtonPaddingHorizontal();
696     auto length = buttons.size();
697     for (size_t i = 0; i < length; ++i) {
698         if (i != 0 && !isVertical) {
699             auto dividerNode = CreateDivider(
700                 dividerLength, dividerWidth, dividerColor, buttonSpace);
701             CHECK_NULL_VOID(dividerNode);
702             container->AddChild(dividerNode);
703         }
704         auto buttonNode = CreateButton(buttons[i], i, false, isVertical, length);
705         CHECK_NULL_VOID(buttonNode);
706         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
707         CHECK_NULL_VOID(buttonPattern);
708         buttonPattern->SetSkipColorConfigurationUpdate();
709         buttonNode->MountToParent(container);
710         buttonNode->MarkModifyDone();
711     }
712 }
713 
CreateButtonText(const std::string & text,const std::string & colorStr)714 RefPtr<FrameNode> DialogPattern::CreateButtonText(const std::string& text, const std::string& colorStr)
715 {
716     auto textNode = FrameNode::CreateFrameNode(
717         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
718     CHECK_NULL_RETURN(textNode, nullptr);
719     textNode->GetOrCreateFocusHub()->SetFocusable(true);
720     auto textProps = textNode->GetLayoutProperty<TextLayoutProperty>();
721     CHECK_NULL_RETURN(textProps, nullptr);
722     textProps->UpdateContent(text);
723     textProps->UpdateFontWeight(FontWeight::MEDIUM);
724     textProps->UpdateMaxLines(1);
725     textProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
726     Dimension buttonTextSize =
727         dialogTheme_->GetButtonTextSize().IsValid() ? dialogTheme_->GetButtonTextSize() : DIALOG_BUTTON_TEXT_SIZE;
728     textProps->UpdateFontSize(buttonTextSize);
729     // update text color
730     Color color;
731     if (Color::ParseColorString(colorStr, color)) {
732         textProps->UpdateTextColor(color);
733     } else {
734         textProps->UpdateTextColor(DEFAULT_BUTTON_COLOR);
735     }
736     return textNode;
737 }
738 
BuildSheetItem(const ActionSheetInfo & item)739 RefPtr<FrameNode> DialogPattern::BuildSheetItem(const ActionSheetInfo& item)
740 {
741     // ListItem -> Row -> title + icon
742     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
743     RefPtr<FrameNode> itemNode = FrameNode::CreateFrameNode(
744         V2::LIST_ITEM_ETS_TAG, Id, AceType::MakeRefPtr<ListItemPattern>(nullptr, V2::ListItemStyle::NONE));
745     CHECK_NULL_RETURN(itemNode, nullptr);
746 
747     // update sheet row flex align
748     auto rowId = ElementRegister::GetInstance()->MakeUniqueId();
749     auto itemRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, rowId, AceType::MakeRefPtr<LinearLayoutPattern>(false));
750     CHECK_NULL_RETURN(itemRow, nullptr);
751     auto layoutProps = itemRow->GetLayoutProperty<LinearLayoutProperty>();
752     layoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
753     layoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
754 
755     // mount icon
756     if (!item.icon.empty()) {
757         auto iconNode = BuildSheetInfoIcon(item.icon);
758         iconNode->MountToParent(itemRow);
759         iconNode->MarkModifyDone();
760     }
761 
762     // mount title
763     if (!item.title.empty()) {
764         auto titleNode = BuildSheetInfoTitle(item.title);
765         titleNode->MountToParent(itemRow);
766         titleNode->MarkModifyDone();
767     }
768 
769     // set sheetItem action
770     auto hub = itemRow->GetOrCreateGestureEventHub();
771     if (item.action) {
772         hub->AddClickEvent(item.action);
773         auto recordEvent = [weak = WeakClaim(this), title = item.title](GestureEvent& info) {
774             if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
775                 return;
776             }
777             auto pattern = weak.Upgrade();
778             CHECK_NULL_VOID(pattern);
779             Recorder::EventParamsBuilder builder;
780             builder.SetEventType(Recorder::EventType::DIALOG_SELECT)
781                 .SetText(title)
782                 .SetExtra(Recorder::KEY_TITLE, pattern->title_)
783                 .SetExtra(Recorder::KEY_SUB_TITLE, pattern->subtitle_);
784             Recorder::EventRecorder::Get().OnEvent(std::move(builder));
785         };
786         auto recordEventPtr = MakeRefPtr<ClickEvent>(std::move(recordEvent));
787         hub->AddClickEvent(recordEventPtr);
788     }
789 
790     // close dialog when clicked
791     BindCloseCallBack(hub, SHEET_INFO_IDX);
792     itemRow->MountToParent(itemNode);
793     return itemNode;
794 }
795 
BuildSheetInfoTitle(const std::string & title)796 RefPtr<FrameNode> DialogPattern::BuildSheetInfoTitle(const std::string& title)
797 {
798     auto titleId = ElementRegister::GetInstance()->MakeUniqueId();
799     auto titleNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, titleId, AceType::MakeRefPtr<TextPattern>());
800     CHECK_NULL_RETURN(titleNode, nullptr);
801     // update text style
802     auto style = dialogTheme_->GetContentTextStyle();
803     auto props = titleNode->GetLayoutProperty<TextLayoutProperty>();
804     props->UpdateContent(title);
805     props->UpdateTextOverflow(TextOverflow::ELLIPSIS);
806     props->UpdateAdaptMaxFontSize(style.GetFontSize());
807     props->UpdateAdaptMinFontSize(dialogTheme_->GetTitleMinFontSize());
808     props->UpdateMaxLines(style.GetMaxLines());
809     props->UpdateFlexGrow(1.0f);
810     props->UpdateFlexShrink(1.0f);
811     return titleNode;
812 }
813 
BuildSheetInfoIcon(const std::string & icon)814 RefPtr<FrameNode> DialogPattern::BuildSheetInfoIcon(const std::string& icon)
815 {
816     auto iconId = ElementRegister::GetInstance()->MakeUniqueId();
817     auto iconNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, iconId, AceType::MakeRefPtr<ImagePattern>());
818     CHECK_NULL_RETURN(iconNode, nullptr);
819     // add image margin
820     MarginProperty margin = {
821         .left = CalcLength(SHEET_IMAGE_MARGIN),
822         .right = CalcLength(SHEET_IMAGE_MARGIN),
823         .top = CalcLength(SHEET_IMAGE_MARGIN),
824         .bottom = CalcLength(SHEET_IMAGE_MARGIN),
825     };
826     auto iconProps = iconNode->GetLayoutProperty<ImageLayoutProperty>();
827     iconProps->UpdateMargin(margin);
828     auto imageSrc = ImageSourceInfo(icon);
829     iconProps->UpdateImageSourceInfo(imageSrc);
830     iconProps->UpdateUserDefinedIdealSize(CalcSize(SHEET_IMAGE_SIZE, SHEET_IMAGE_SIZE));
831     return iconNode;
832 }
833 
BuildSheet(const std::vector<ActionSheetInfo> & sheets)834 RefPtr<FrameNode> DialogPattern::BuildSheet(const std::vector<ActionSheetInfo>& sheets)
835 {
836     auto listId = ElementRegister::GetInstance()->MakeUniqueId();
837     auto list = FrameNode::CreateFrameNode(V2::LIST_ETS_TAG, listId, AceType::MakeRefPtr<ListPattern>());
838     CHECK_NULL_RETURN(list, nullptr);
839 
840     // set sheet padding
841     CalcLength padding(SHEET_LIST_PADDING.ConvertToPx());
842     PaddingProperty sheetPadding = {
843         .left = padding,
844         .right = padding,
845         .top = padding,
846         .bottom = padding,
847     };
848     list->GetLayoutProperty()->UpdatePadding(sheetPadding);
849     list->GetPaintProperty<ScrollablePaintProperty>()->UpdateScrollBarMode(DisplayMode::OFF);
850 
851     for (auto&& item : sheets) {
852         auto itemNode = BuildSheetItem(item);
853         CHECK_NULL_RETURN(itemNode, nullptr);
854         list->AddChild(itemNode);
855     }
856 
857     // set list divider
858     auto divider = V2::ItemDivider {
859         .strokeWidth = SHEET_DIVIDER_WIDTH,
860         .color = Color::GRAY,
861     };
862     auto props = list->GetLayoutProperty<ListLayoutProperty>();
863     props->UpdateDivider(divider);
864     props->UpdateListDirection(Axis::VERTICAL);
865     return list;
866 }
867 
BuildMenu(const std::vector<ButtonInfo> & buttons,bool hasTitle)868 RefPtr<FrameNode> DialogPattern::BuildMenu(const std::vector<ButtonInfo>& buttons, bool hasTitle)
869 {
870     auto menu = FrameNode::CreateFrameNode(
871         V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(true));
872     menuNode_ = menu;
873     // column -> button
874     for (size_t i = 0; i < buttons.size(); ++i) {
875         RefPtr<FrameNode> button;
876         if (i != (buttons.size() - 1)) {
877             button = CreateButton(buttons[i], i);
878         } else {
879             button = CreateButton(buttons[i], i, true);
880         }
881         CHECK_NULL_RETURN(button, nullptr);
882         auto props = DynamicCast<FrameNode>(button)->GetLayoutProperty();
883         auto buttonRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
884         AceType::MakeRefPtr<LinearLayoutPattern>(false));
885         CHECK_NULL_RETURN(buttonRow, nullptr);
886         auto buttonRowProps = buttonRow->GetLayoutProperty<LinearLayoutProperty>();
887         CHECK_NULL_RETURN(buttonRowProps, nullptr);
888         buttonRowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
889         buttonRowProps->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
890 
891         button->MountToParent(buttonRow);
892         button->MarkModifyDone();
893         menu->AddChild(buttonRow);
894     }
895     auto menuProps = menu->GetLayoutProperty<LinearLayoutProperty>();
896     CHECK_NULL_RETURN(menuProps, nullptr);
897     PaddingProperty menuPadding;
898     if (!hasTitle) {
899         menuPadding.top = CalcLength(dialogTheme_->GetContentAdjustPadding().Top());
900     }
901     menuPadding.left = CalcLength(dialogTheme_->GetDefaultPadding().Left());
902     menuPadding.right = CalcLength(dialogTheme_->GetDefaultPadding().Right());
903     menuPadding.bottom = CalcLength(dialogTheme_->GetButtonPaddingBottom());
904     menuProps->UpdatePadding(menuPadding);
905     return menu;
906 }
907 
RegisterOnKeyEvent(const RefPtr<FocusHub> & focusHub)908 void DialogPattern::RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub)
909 {
910     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
911         auto pattern = wp.Upgrade();
912         CHECK_NULL_RETURN(pattern, false);
913         return pattern->OnKeyEvent(event);
914     };
915     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
916 }
917 
OnKeyEvent(const KeyEvent & event)918 bool DialogPattern::OnKeyEvent(const KeyEvent& event)
919 {
920     if (event.action != KeyAction::DOWN) {
921         return false;
922     }
923     return false;
924 }
925 
926 // XTS inspector
ToJsonValue(std::unique_ptr<JsonValue> & json) const927 void DialogPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
928 {
929     auto host = GetHost();
930     CHECK_NULL_VOID(host);
931     if (host->GetTag() == V2::ALERT_DIALOG_ETS_TAG || host->GetTag() == V2::ACTION_SHEET_DIALOG_ETS_TAG) {
932         json->Put("title", title_.c_str());
933         json->Put("subtitle", subtitle_.c_str());
934         json->Put("message", message_.c_str());
935     }
936 }
937 
OnColorConfigurationUpdate()938 void DialogPattern::OnColorConfigurationUpdate()
939 {
940     auto host = GetHost();
941     CHECK_NULL_VOID(host);
942     auto context = host->GetContext();
943     CHECK_NULL_VOID(context);
944     auto dialogTheme = context->GetTheme<DialogTheme>();
945     CHECK_NULL_VOID(dialogTheme);
946     UpdateWrapperBackgroundStyle(host, dialogTheme);
947     CHECK_NULL_VOID(buttonContainer_);
948     int32_t btnIndex = 0;
949     for (const auto& buttonNode : buttonContainer_->GetChildren()) {
950         if (buttonNode->GetTag() != V2::BUTTON_ETS_TAG) {
951             continue;
952         }
953         auto buttonFrameNode = DynamicCast<FrameNode>(buttonNode);
954         CHECK_NULL_VOID(buttonFrameNode);
955         auto pattern = buttonFrameNode->GetPattern<ButtonPattern>();
956         CHECK_NULL_VOID(pattern);
957         pattern->SetSkipColorConfigurationUpdate();
958         auto buttonTextNode = DynamicCast<FrameNode>(buttonFrameNode->GetFirstChild());
959         CHECK_NULL_VOID(buttonTextNode);
960         auto buttonTextLayoutProperty = buttonTextNode->GetLayoutProperty<TextLayoutProperty>();
961         CHECK_NULL_VOID(buttonTextLayoutProperty);
962         auto textColorStr = dialogProperties_.buttons[btnIndex].textColor;
963         if (!textColorStr.empty()) {
964             Color textColor;
965             Color::ParseColorString(textColorStr, textColor);
966             buttonTextLayoutProperty->UpdateTextColor(textColor);
967         } else {
968             buttonTextLayoutProperty->UpdateTextColor(dialogTheme->GetButtonDefaultFontColor());
969         }
970         buttonTextNode->MarkModifyDone();
971         buttonTextNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
972         ++btnIndex;
973     }
974     OnModifyDone();
975     host->MarkDirtyNode();
976 }
977 
SetButtonEnabled(const RefPtr<FrameNode> & buttonNode,bool enabled)978 void DialogPattern::SetButtonEnabled(const RefPtr<FrameNode>& buttonNode, bool enabled)
979 {
980     // set Enabled and Focusable
981     auto buttonButtonEvent = buttonNode->GetEventHub<ButtonEventHub>();
982     CHECK_NULL_VOID(buttonButtonEvent);
983     buttonButtonEvent->SetEnabled(enabled);
984     buttonNode->GetOrCreateFocusHub()->SetFocusable(enabled);
985 }
986 
UpdateWrapperBackgroundStyle(const RefPtr<FrameNode> & host,const RefPtr<DialogTheme> & dialogTheme)987 void DialogPattern::UpdateWrapperBackgroundStyle(const RefPtr<FrameNode>& host, const RefPtr<DialogTheme>& dialogTheme)
988 {
989     auto col = DynamicCast<FrameNode>(host->GetChildAtIndex(START_CHILD_INDEX));
990     CHECK_NULL_VOID(col);
991     auto colRenderContext = col->GetRenderContext();
992     CHECK_NULL_VOID(colRenderContext);
993     if (!GetDialogProperties().customStyle) {
994         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) || !colRenderContext->IsUniRenderEnabled()) {
995             colRenderContext->UpdateBackgroundColor(dialogTheme->GetBackgroundColor());
996         } else if (!GetDialogProperties().isSysBlurStyle) {
997             colRenderContext->UpdateBackBlurStyle(colRenderContext->GetBackBlurStyle());
998         }
999     }
1000     if (colRenderContext->GetBackBlurStyle().has_value()) {
1001         colRenderContext->UpdateBackBlurStyle(colRenderContext->GetBackBlurStyle());
1002     }
1003 }
1004 } // namespace OHOS::Ace::NG
1005