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