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