1 /*
2 * Copyright (c) 2022-2024 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
16 #include "core/components_ng/pattern/container_modal/container_modal_view.h"
17
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/image/pixel_map.h"
20 #include "base/subwindow/subwindow_manager.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/components_ng/gestures/pan_gesture.h"
24 #include "core/components_ng/gestures/tap_gesture.h"
25 #include "core/components_ng/pattern/button/button_layout_property.h"
26 #include "core/components_ng/pattern/button/button_pattern.h"
27 #include "core/components_ng/pattern/container_modal/container_modal_theme.h"
28 #include "core/components_ng/pattern/container_modal/container_modal_utils.h"
29 #include "core/components_ng/pattern/image/image_pattern.h"
30 #include "core/components_ng/pattern/image/image_render_property.h"
31 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
32 #include "core/components_ng/pattern/stack/stack_pattern.h"
33 #include "core/components_ng/pattern/text/text_layout_property.h"
34 #include "core/components_ng/pattern/text/text_pattern.h"
35 #include "core/components_ng/pattern/toolbaritem/toolbar_row_pattern.h"
36
37 namespace OHOS::Ace::NG {
38 namespace {
39 constexpr char SPLIT_LEFT_KEY[] = "container_modal_split_left_button";
40 constexpr char MAXIMIZE_KEY[] = "container_modal_maximize_button";
41 constexpr char MINIMIZE_KEY[] = "container_modal_minimize_button";
42 constexpr char CLOSE_KEY[] = "container_modal_close_button";
43 constexpr float SPRINGMOTION_RESPONSE = 0.55f;
44 constexpr float CURRENT_RATIO = 0.86f;
45 constexpr float CURRENT_DURATION = 0.25f;
46 } // namespace
47 float ContainerModalView::baseScale = 1.0f;
48 std::function<RefPtr<NG::FrameNode>()> ContainerModalView::customTitileBuilder_ = nullptr;
49 std::function<RefPtr<NG::FrameNode>(
50 const WeakPtr<NG::ContainerModalPatternEnhance>& weakPattern, const RefPtr<NG::FrameNode>& containerTitleRow)>
51 ContainerModalView::customControlButtonBuilder_ = nullptr;
52
53 /**
54 * The structure of container_modal is designed as follows :
55 * |--container_modal(stack)
56 * |--column
57 * |--container_modal_custom_title(row)
58 * |--custom_node(js)
59 * |--stack
60 * |--container_modal_content(stage)
61 * |--page
62 * |--dialog(when show)
63 * |--container_modal_custom_floating_title(row)
64 * |--custom_node(js)
65 * |--container_modal_control_buttons(row)
66 * |--[leftSplit, maxRecover, minimize, close](button)
67 */
68
Create(RefPtr<FrameNode> & content)69 RefPtr<FrameNode> ContainerModalView::Create(RefPtr<FrameNode>& content)
70 {
71 auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
72 ACE_LAYOUT_SCOPED_TRACE("Create[ContainerModal][self:%d]", nodeId);
73 auto containerModalNode = FrameNode::CreateFrameNode("ContainerModal", nodeId, MakeRefPtr<ContainerModalPattern>());
74 auto stack = FrameNode::CreateFrameNode(
75 V2::STACK_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<StackPattern>());
76 auto column = FrameNode::CreateFrameNode(
77 V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(true));
78 auto controlButtonsRow = FrameNode::CreateFrameNode(
79 V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(false));
80
81 column->AddChild(BuildTitle(containerModalNode));
82 stack->AddChild(content);
83 column->AddChild(stack);
84 auto containerPattern = containerModalNode->GetPattern<ContainerModalPattern>();
85 CHECK_NULL_RETURN(containerPattern, nullptr);
86 containerModalNode->AddChild(column);
87 containerModalNode->AddChild(BuildTitle(containerModalNode, true));
88 containerModalNode->AddChild(AddControlButtons(controlButtonsRow));
89
90 containerPattern->Init();
91
92 return containerModalNode;
93 }
94
BuildTitle(RefPtr<FrameNode> & containerNode,bool isFloatingTitle)95 RefPtr<FrameNode> ContainerModalView::BuildTitle(RefPtr<FrameNode>& containerNode, bool isFloatingTitle)
96 {
97 TAG_LOGI(AceLogTag::ACE_APPBAR, "ContainerModalView BuildTitle called");
98 auto customTitleContainer = BuildTitleContainer(containerNode, isFloatingTitle);
99 CHECK_NULL_RETURN(customTitleContainer, nullptr);
100 return customTitleContainer;
101 }
102
BuildTitleContainer(RefPtr<FrameNode> & containerNode,bool isFloatingTitle)103 RefPtr<FrameNode> ContainerModalView::BuildTitleContainer(RefPtr<FrameNode>& containerNode, bool isFloatingTitle)
104 {
105 auto containerTitleRow = BuildTitleRow(isFloatingTitle);
106 CHECK_NULL_RETURN(containerTitleRow, nullptr);
107
108 RefPtr<UINode> customTitleBarNode;
109 if (customTitileBuilder_) {
110 customTitleBarNode = customTitileBuilder_();
111 } else {
112 auto isSucc = ExecuteCustomTitleAbc();
113 if (!isSucc) {
114 return nullptr;
115 }
116 customTitleBarNode = NG::ViewStackProcessor::GetInstance()->GetCustomTitleNode();
117 }
118
119 CHECK_NULL_RETURN(customTitleBarNode, nullptr);
120 auto customTitleBarRow = FrameNode::CreateFrameNode(
121 V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<LinearLayoutPattern>(false));
122 customTitleBarRow->AddChild(customTitleBarNode);
123 containerTitleRow->AddChild(customTitleBarRow);
124 return containerTitleRow;
125 }
126
RegistCustomBuilder(std::function<RefPtr<NG::FrameNode> ()> & title,std::function<RefPtr<NG::FrameNode> (const WeakPtr<NG::ContainerModalPatternEnhance> & weakPattern,const RefPtr<NG::FrameNode> & containerTitleRow)> & button)127 void ContainerModalView::RegistCustomBuilder(std::function<RefPtr<NG::FrameNode>()>& title,
128 std::function<RefPtr<NG::FrameNode>(const WeakPtr<NG::ContainerModalPatternEnhance>& weakPattern,
129 const RefPtr<NG::FrameNode>& containerTitleRow)>& button)
130 {
131 customTitileBuilder_ = title;
132 customControlButtonBuilder_ = button;
133 }
134
BuildTitleRow(bool isFloatingTitle)135 RefPtr<FrameNode> ContainerModalView::BuildTitleRow(bool isFloatingTitle)
136 {
137 auto containerTitleRow = FrameNode::CreateFrameNode(
138 V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ToolBarRowPattern>());
139 containerTitleRow->UpdateInspectorId("ContainerModalTitleRow");
140 if (isFloatingTitle) {
141 auto renderContext = containerTitleRow->GetRenderContext();
142 CHECK_NULL_RETURN(renderContext, nullptr);
143 auto pipeline = PipelineContext::GetCurrentContext();
144 CHECK_NULL_RETURN(pipeline, nullptr);
145 auto theme = pipeline->GetTheme<ContainerModalTheme>();
146 renderContext->UpdateBackgroundColor(theme->GetBackGroundColor(true));
147 }
148 return containerTitleRow;
149 }
150
AddControlButtons(RefPtr<FrameNode> & controlButtonsRow)151 RefPtr<FrameNode> ContainerModalView::AddControlButtons(RefPtr<FrameNode>& controlButtonsRow)
152 {
153 auto pipeline = PipelineContext::GetCurrentContext();
154 CHECK_NULL_RETURN(pipeline, nullptr);
155 auto windowManager = pipeline->GetWindowManager();
156 CHECK_NULL_RETURN(windowManager, nullptr);
157
158 // add leftSplit / maxRecover / minimize / close button
159 controlButtonsRow->AddChild(BuildControlButton(InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT,
160 [wk = WeakClaim(RawPtr(windowManager))](GestureEvent& info) {
161 auto windowManager = wk.Upgrade();
162 CHECK_NULL_VOID(windowManager);
163 TAG_LOGI(AceLogTag::ACE_APPBAR, "left split button clicked");
164 windowManager->FireWindowSplitCallBack();
165 }));
166 controlButtonsRow->AddChild(BuildControlButton(InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE,
167 [wk = WeakClaim(RawPtr(windowManager))](GestureEvent& info) {
168 auto windowManager = wk.Upgrade();
169 CHECK_NULL_VOID(windowManager);
170 auto mode = windowManager->GetWindowMode();
171 if (mode == WindowMode::WINDOW_MODE_FULLSCREEN) {
172 TAG_LOGI(AceLogTag::ACE_APPBAR, "recover button clicked");
173 windowManager->WindowRecover();
174 } else {
175 TAG_LOGI(AceLogTag::ACE_APPBAR, "maximize button clicked");
176 windowManager->WindowMaximize();
177 }
178 }));
179 controlButtonsRow->AddChild(BuildControlButton(InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE,
180 [wk = WeakClaim(RawPtr(windowManager))](GestureEvent& info) {
181 auto windowManager = wk.Upgrade();
182 CHECK_NULL_VOID(windowManager);
183 TAG_LOGI(AceLogTag::ACE_APPBAR, "minimize button clicked");
184 windowManager->WindowMinimize();
185 }));
186 controlButtonsRow->AddChild(BuildControlButton(
187 InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE,
188 [wk = WeakClaim(RawPtr(windowManager))](GestureEvent& info) {
189 auto windowManager = wk.Upgrade();
190 CHECK_NULL_VOID(windowManager);
191 TAG_LOGI(AceLogTag::ACE_APPBAR, "close button clicked");
192 windowManager->WindowClose();
193 },
194 true));
195
196 return controlButtonsRow;
197 }
198
BuildControlButton(InternalResource::ResourceId icon,GestureEventFunc && clickCallback,bool isCloseButton,bool canDrag)199 RefPtr<FrameNode> ContainerModalView::BuildControlButton(
200 InternalResource::ResourceId icon, GestureEventFunc&& clickCallback, bool isCloseButton, bool canDrag)
201 {
202 static std::unordered_map<InternalResource::ResourceId, std::string> controlButtonKeyMap = {
203 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT, SPLIT_LEFT_KEY },
204 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_SPLIT_LEFT, SPLIT_LEFT_KEY },
205 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_RECOVER, MAXIMIZE_KEY },
206 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE, MAXIMIZE_KEY },
207 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_RECOVER, MAXIMIZE_KEY },
208 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MAXIMIZE, MAXIMIZE_KEY },
209 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE, MINIMIZE_KEY },
210 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_MINIMIZE, MINIMIZE_KEY },
211 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE, CLOSE_KEY },
212 { InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_CLOSE, CLOSE_KEY },
213 };
214 auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
215 CHECK_NULL_RETURN(theme, nullptr);
216 // button image icon
217 ImageSourceInfo imageSourceInfo;
218 auto imageIcon = FrameNode::CreateFrameNode(
219 V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ImagePattern>());
220 auto imageEventHub = imageIcon->GetOrCreateGestureEventHub();
221 CHECK_NULL_RETURN(imageEventHub, nullptr);
222 imageEventHub->RemoveDragEvent();
223 imageIcon->SetDraggable(false);
224 auto imageFocus = imageIcon->GetFocusHub();
225 if (imageFocus) {
226 imageFocus->SetFocusable(false);
227 }
228 imageSourceInfo.SetResourceId(icon);
229 imageSourceInfo.SetFillColor(theme->GetControlBtnColor(isCloseButton, ControlBtnColorType::NORMAL_FILL));
230 auto imageLayoutProperty = imageIcon->GetLayoutProperty<ImageLayoutProperty>();
231 CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
232 imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(TITLE_ICON_SIZE), CalcLength(TITLE_ICON_SIZE)));
233 imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
234 auto imageRenderProperty = imageIcon->GetPaintProperty<ImageRenderProperty>();
235 CHECK_NULL_RETURN(imageRenderProperty, nullptr);
236 imageRenderProperty->UpdateImageInterpolation(ImageInterpolation::HIGH);
237 imageIcon->MarkModifyDone();
238
239 auto buttonNode = FrameNode::CreateFrameNode(
240 V2::BUTTON_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<ButtonPattern>());
241 auto buttonFocus = buttonNode->GetFocusHub();
242 if (buttonFocus) {
243 buttonFocus->SetFocusable(false);
244 }
245 std::string buttonKey = "";
246 auto iter = controlButtonKeyMap.find(icon);
247 if (iter != controlButtonKeyMap.end()) {
248 buttonKey = iter->second;
249 }
250 buttonNode->UpdateInspectorId(buttonKey);
251
252 AddButtonHover(buttonNode, imageIcon);
253 AddButtonMouse(buttonNode, imageIcon);
254 AddButtonStyleMouseEvent(buttonNode, imageIcon, isCloseButton);
255
256 auto renderContext = buttonNode->GetRenderContext();
257 CHECK_NULL_RETURN(renderContext, nullptr);
258 renderContext->UpdateBackgroundColor(theme->GetControlBtnColor(isCloseButton, ControlBtnColorType::NORMAL));
259
260 auto buttonEventHub = buttonNode->GetOrCreateGestureEventHub();
261 CHECK_NULL_RETURN(buttonEventHub, nullptr);
262 auto clickGesture = MakeRefPtr<TapGesture>();
263 clickGesture->SetOnActionId(clickCallback);
264 buttonEventHub->AddGesture(clickGesture);
265 buttonNode->SetDraggable(canDrag);
266
267 DimensionOffset offsetDimen(TITLE_BUTTON_RESPONSE_REGIOIN_OFFSET_X, TITLE_BUTTON_RESPONSE_REGIOIN_OFFSET_Y);
268 DimensionRect dimenRect(TITLE_BUTTON_RESPONSE_REGIOIN_WIDTH, TITLE_BUTTON_RESPONSE_REGIOIN_HEIGHT, offsetDimen);
269 std::vector<DimensionRect> result;
270 result.emplace_back(dimenRect);
271 auto gestureHub = buttonNode->GetOrCreateGestureEventHub();
272 CHECK_NULL_RETURN(gestureHub, nullptr);
273 gestureHub->SetResponseRegion(result);
274
275 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
276 CHECK_NULL_RETURN(buttonLayoutProperty, nullptr);
277 buttonLayoutProperty->UpdateType(ButtonType::CIRCLE);
278 buttonLayoutProperty->UpdateUserDefinedIdealSize(
279 CalcSize(CalcLength(TITLE_BUTTON_SIZE), CalcLength(TITLE_BUTTON_SIZE)));
280
281 MarginProperty margin;
282 margin.right = CalcLength(isCloseButton ? TITLE_PADDING_END : TITLE_ELEMENT_MARGIN_HORIZONTAL);
283 buttonLayoutProperty->UpdateMargin(margin);
284 buttonNode->MarkModifyDone();
285
286 buttonNode->AddChild(imageIcon);
287 return buttonNode;
288 }
289
AddButtonHover(RefPtr<FrameNode> & buttonNode,RefPtr<FrameNode> & imageNode)290 void ContainerModalView::AddButtonHover(RefPtr<FrameNode>& buttonNode, RefPtr<FrameNode>& imageNode)
291 {
292 auto inputHub = buttonNode->GetOrCreateInputEventHub();
293 CHECK_NULL_VOID(inputHub);
294 auto hoverTask = [buttonWk = WeakClaim(RawPtr(buttonNode)), imageWk = WeakClaim(RawPtr(imageNode))](bool isHover) {
295 auto buttonNode = buttonWk.Upgrade();
296 auto imageNode = imageWk.Upgrade();
297 CHECK_NULL_VOID(buttonNode && imageNode);
298 auto buttonPattern = DynamicCast<ButtonPattern>(buttonNode->GetPattern());
299 CHECK_NULL_VOID(buttonPattern);
300 buttonPattern->SetInHover(isHover);
301 float halfSize = TITLE_ICON_SIZE.Value() / 2.0f;
302 auto icurve = MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.2f, 1.0f);
303 float maxDis = sqrt(pow(halfSize, 2.0) + pow(halfSize, 2.0));
304 float curDis = sqrt(pow(buttonPattern->GetLocalLocation().GetX() - halfSize, 2.0) +
305 pow(buttonPattern->GetLocalLocation().GetY() - halfSize, 2.0));
306 float currentScale = 1 + 0.1 * icurve->Move((maxDis - curDis) / (maxDis));
307 baseScale = currentScale > baseScale ? currentScale : baseScale;
308 auto buttonNodeRenderContext = buttonNode->GetRenderContext();
309 auto imageIconRenderContext = imageNode->GetRenderContext();
310 CHECK_NULL_VOID(buttonNodeRenderContext);
311 CHECK_NULL_VOID(imageIconRenderContext);
312 float imageScale = isHover ? baseScale : 1.0f;
313 float btnScale = 1.0f;
314 AnimationOption option = AnimationOption();
315 auto motion = MakeRefPtr<ResponsiveSpringMotion>(SPRINGMOTION_RESPONSE, CURRENT_RATIO, CURRENT_DURATION);
316 option.SetCurve(motion);
317 if (isHover) {
318 AnimationUtils::Animate(option, [buttonNodeRenderContext, imageIconRenderContext, imageScale, btnScale]() {
319 buttonNodeRenderContext->UpdateTransformScale(VectorF(btnScale, btnScale));
320 imageIconRenderContext->UpdateTransformScale(VectorF(1 / imageScale, 1 / imageScale));
321 });
322 } else {
323 baseScale = 1.0f;
324 AnimationUtils::Animate(option, [buttonNodeRenderContext, imageIconRenderContext, imageScale, btnScale]() {
325 buttonNodeRenderContext->UpdateTransformScale(VectorF(btnScale, btnScale));
326 imageIconRenderContext->UpdateTransformScale(VectorF(imageScale, imageScale));
327 });
328 }
329 };
330 auto hoverEvent = MakeRefPtr<InputEvent>(std::move(hoverTask));
331 inputHub->AddOnHoverEvent(hoverEvent);
332 }
333
AddButtonMouse(RefPtr<FrameNode> & buttonNode,RefPtr<FrameNode> & imageNode)334 void ContainerModalView::AddButtonMouse(RefPtr<FrameNode>& buttonNode, RefPtr<FrameNode>& imageNode)
335 {
336 auto inputHub = buttonNode->GetOrCreateInputEventHub();
337 CHECK_NULL_VOID(inputHub);
338 auto mouseTask = [buttonWk = WeakClaim(RawPtr(buttonNode)), imageWk = WeakClaim(RawPtr(imageNode))](
339 MouseInfo& info) {
340 auto buttonNode = buttonWk.Upgrade();
341 auto imageNode = imageWk.Upgrade();
342 CHECK_NULL_VOID(buttonNode && imageNode);
343 auto buttonPattern = DynamicCast<ButtonPattern>(buttonNode->GetPattern());
344 CHECK_NULL_VOID(buttonPattern);
345 if (info.GetAction() != MouseAction::MOVE || !buttonPattern->GetIsInHover()) {
346 buttonPattern->SetLocalLocation(info.GetLocalLocation());
347 return;
348 }
349 auto buttonNodeRenderContext = buttonNode->GetRenderContext();
350 auto imageIconRenderContext = imageNode->GetRenderContext();
351 CHECK_NULL_VOID(imageIconRenderContext);
352 float halfSize = TITLE_ICON_SIZE.Value() / 2.0f;
353 auto icurve = MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.2f, 1.0f);
354 float maxDis = sqrt(pow(halfSize, 2.0) + pow(halfSize, 2.0));
355 float curDis = sqrt(
356 pow(info.GetLocalLocation().GetX() - halfSize, 2.0) + pow(info.GetLocalLocation().GetY() - halfSize, 2.0));
357 float currentScale = 1 + 0.1 * icurve->Move((maxDis - curDis) / (maxDis));
358 baseScale = currentScale > baseScale ? currentScale : baseScale;
359 float imageScale = baseScale;
360 float btnScale = 1.0f;
361 float response = ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE;
362 float dampingRatio = ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO;
363 float blendDuration = ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION;
364 auto motion = MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
365 AnimationOption option = AnimationOption();
366 option.SetCurve(motion);
367 AnimationUtils::Animate(option, [buttonNodeRenderContext, imageIconRenderContext, imageScale, btnScale]() {
368 buttonNodeRenderContext->UpdateTransformScale(VectorF(btnScale, btnScale));
369 imageIconRenderContext->UpdateTransformScale(VectorF(imageScale, imageScale));
370 });
371 };
372 auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseTask));
373 inputHub->AddOnMouseEvent(mouseEvent);
374 }
375
AddButtonStyleMouseEvent(RefPtr<FrameNode> & buttonNode,RefPtr<FrameNode> & imageNode,bool isCloseBtn)376 void ContainerModalView::AddButtonStyleMouseEvent(
377 RefPtr<FrameNode>& buttonNode, RefPtr<FrameNode>& imageNode, bool isCloseBtn)
378 {
379 auto inputHub = buttonNode->GetOrCreateInputEventHub();
380 CHECK_NULL_VOID(inputHub);
381 AddButtonHoverEvent(inputHub, buttonNode, imageNode, isCloseBtn);
382 AddButtonOnEvent(inputHub, buttonNode, imageNode, isCloseBtn);
383 }
384
AddButtonHoverEvent(RefPtr<InputEventHub> & inputHub,RefPtr<FrameNode> & buttonNode,RefPtr<FrameNode> & imageNode,bool isCloseBtn)385 void ContainerModalView::AddButtonHoverEvent(
386 RefPtr<InputEventHub>& inputHub, RefPtr<FrameNode>& buttonNode, RefPtr<FrameNode>& imageNode, bool isCloseBtn)
387 {
388 auto task = [buttonWk = WeakClaim(RawPtr(buttonNode)), imageWk = WeakClaim(RawPtr(imageNode)), isCloseBtn](
389 bool isHover) {
390 auto buttonNode = buttonWk.Upgrade();
391 CHECK_NULL_VOID(buttonNode);
392 auto imageNode = imageWk.Upgrade();
393 CHECK_NULL_VOID(imageNode);
394 auto pipeline = buttonNode->GetContextRefPtr();
395 CHECK_NULL_VOID(pipeline);
396 auto containerNode = AceType::DynamicCast<FrameNode>(pipeline->GetRootElement()->GetChildAtIndex(0));
397 auto containerModalPattern = containerNode->GetPattern<ContainerModalPattern>();
398 CHECK_NULL_VOID(containerModalPattern);
399 bool isFocus = containerModalPattern->GetIsFocus() || containerModalPattern->GetIsHoveredMenu();
400
401 auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
402 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
403 auto sourceInfo = imageLayoutProperty->GetImageSourceInfo();
404 ControlBtnColorType isHoverFillType = ControlBtnColorType::HOVER_FILL;
405 ControlBtnColorType isHoverType = ControlBtnColorType::HOVER;
406 if (!isHover) {
407 isHoverFillType = isFocus ? ControlBtnColorType::NORMAL_FILL : ControlBtnColorType::UNFOCUS_FILL;
408 isHoverType = isFocus ? ControlBtnColorType::NORMAL : ControlBtnColorType::UNFOCUS;
409 }
410 sourceInfo->SetFillColor(theme->GetControlBtnColor(isCloseBtn, isHoverFillType));
411 if (isCloseBtn) {
412 auto renderContext = buttonNode->GetRenderContext();
413 renderContext->UpdateBackgroundColor(theme->GetControlBtnColor(isCloseBtn, isHoverType));
414 }
415 if (sourceInfo.has_value()) {
416 imageLayoutProperty->UpdateImageSourceInfo(sourceInfo.value());
417 }
418 buttonNode->MarkModifyDone();
419 imageNode->MarkModifyDone();
420 };
421 auto hoverCallBack = MakeRefPtr<InputEvent>(std::move(task));
422 inputHub->AddOnHoverEvent(hoverCallBack);
423 }
424
AddButtonOnEvent(RefPtr<InputEventHub> & inputHub,RefPtr<FrameNode> & buttonNode,RefPtr<FrameNode> & imageNode,bool isCloseBtn)425 void ContainerModalView::AddButtonOnEvent(
426 RefPtr<InputEventHub>& inputHub, RefPtr<FrameNode>& buttonNode, RefPtr<FrameNode>& imageNode, bool isCloseBtn)
427 {
428 auto wkTask = [buttonWk = WeakClaim(RawPtr(buttonNode)), imageWk = WeakClaim(RawPtr(imageNode)), isCloseBtn](
429 MouseInfo& info) {
430 auto buttonNode = buttonWk.Upgrade();
431 CHECK_NULL_VOID(buttonNode);
432 auto imageNode = imageWk.Upgrade();
433 CHECK_NULL_VOID(imageNode);
434 auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
435 if (info.GetAction() == MouseAction::PRESS || info.GetAction() == MouseAction::RELEASE) {
436 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
437 CHECK_NULL_VOID(imageLayoutProperty);
438 auto sourceInfo = imageLayoutProperty->GetImageSourceInfo();
439 CHECK_NULL_VOID(sourceInfo);
440 auto isHoverFillType = info.GetAction() == MouseAction::PRESS ? ControlBtnColorType::PRESS_FILL
441 : ControlBtnColorType::NORMAL_FILL;
442 sourceInfo->SetFillColor(theme->GetControlBtnColor(isCloseBtn, isHoverFillType));
443 auto renderContext = buttonNode->GetRenderContext();
444 auto isHoverType =
445 info.GetAction() == MouseAction::PRESS ? ControlBtnColorType::PRESS : ControlBtnColorType::NORMAL;
446 renderContext->UpdateBackgroundColor(theme->GetControlBtnColor(isCloseBtn, isHoverType));
447 buttonNode->MarkModifyDone();
448 imageNode->MarkModifyDone();
449 }
450 };
451 auto onclickCallback = MakeRefPtr<InputEvent>(std::move(wkTask));
452 inputHub->AddOnMouseEvent(onclickCallback);
453 }
454
ConfigCustomWindowMask(RefPtr<PipelineContext> & pipeline,bool enable)455 bool ContainerModalView::ConfigCustomWindowMask(RefPtr<PipelineContext>& pipeline, bool enable)
456 {
457 CHECK_NULL_RETURN(pipeline, false);
458 auto rootNode = pipeline->GetRootElement();
459 CHECK_NULL_RETURN(rootNode, false);
460 if (!enable) {
461 auto customWindowMaskNode = NG::ViewStackProcessor::GetInstance()->GetCustomWindowMaskNode();
462 CHECK_NULL_RETURN(customWindowMaskNode, false);
463 rootNode->RemoveChild(customWindowMaskNode);
464 rootNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE_SELF);
465 return true;
466 }
467 auto isSucc = ExecuteCustomWindowMaskAbc();
468 if (!isSucc) {
469 return false;
470 }
471 auto customWindowMaskNode = NG::ViewStackProcessor::GetInstance()->GetCustomWindowMaskNode();
472 CHECK_NULL_RETURN(customWindowMaskNode, false);
473 customWindowMaskNode->MountToParent(rootNode);
474 rootNode->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE_SELF);
475 return true;
476 }
477 } // namespace OHOS::Ace::NG