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 
16 #include "core/components_ng/pattern/side_bar/side_bar_container_pattern.h"
17 
18 #include <optional>
19 
20 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
21 #include "accessibility_element_info.h"
22 #endif
23 #include "base/log/log_wrapper.h"
24 #include "base/memory/ace_type.h"
25 #include "base/mousestyle/mouse_style.h"
26 #include "base/resource/internal_resource.h"
27 #include "base/utils/utils.h"
28 #include "core/common/ace_application_info.h"
29 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
30 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
31 #include "core/common/container.h"
32 #include "core/common/recorder/event_recorder.h"
33 #include "core/components/common/layout/constants.h"
34 #include "core/components/common/properties/shadow_config.h"
35 #include "core/components_ng/base/frame_node.h"
36 #include "core/components_ng/pattern/button/button_layout_property.h"
37 #include "core/components_ng/pattern/button/button_pattern.h"
38 #include "core/components_ng/pattern/divider/divider_layout_property.h"
39 #include "core/components_ng/pattern/divider/divider_pattern.h"
40 #include "core/components_ng/pattern/divider/divider_render_property.h"
41 #include "core/components_ng/pattern/image/image_layout_property.h"
42 #include "core/components_ng/pattern/image/image_pattern.h"
43 #include "core/components_ng/pattern/side_bar/side_bar_container_paint_method.h"
44 #include "core/components_ng/pattern/side_bar/side_bar_theme.h"
45 #include "core/components_ng/pattern/text/text_layout_property.h"
46 #include "core/components_ng/pattern/text/text_pattern.h"
47 #include "core/components_ng/property/measure_utils.h"
48 #include "core/components_v2/inspector/inspector_constants.h"
49 #include "core/image/image_source_info.h"
50 #include "core/pipeline_ng/pipeline_context.h"
51 #include "core/pipeline_ng/ui_task_scheduler.h"
52 
53 namespace OHOS::Ace::NG {
54 
55 namespace {
56 constexpr int32_t DEFAULT_MIN_CHILDREN_SIZE = 3;
57 constexpr int32_t DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_VALUE = 2;
58 constexpr float RATIO_NEGATIVE = -1.0f;
59 constexpr float RATIO_ZERO = 0.0f;
60 constexpr float DEFAULT_SIDE_BAR_MASK_OPACITY = 0.6f;
61 constexpr Dimension DEFAULT_DRAG_REGION = 20.0_vp;
62 constexpr int32_t SIDEBAR_DURATION = 500;
63 const RefPtr<CubicCurve> SIDEBAR_CURVE = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.2f, 0.1f, 1.0f);
64 constexpr Dimension DEFAULT_DIVIDER_STROKE_WIDTH = 1.0_vp;
65 constexpr Dimension DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_VP = 2.0_vp;
66 constexpr Color DEFAULT_DIVIDER_COLOR = Color(0x08000000);
67 constexpr static int32_t PLATFORM_VERSION_TEN = 10;
68 constexpr static int32_t SIDE_BAR_INDEX = 2;
69 constexpr static int32_t CONTENT_INDEX = 3;
70 Dimension DEFAULT_CONTROL_BUTTON_WIDTH = 32.0_vp;
71 Dimension DEFAULT_CONTROL_BUTTON_HEIGHT = 32.0_vp;
72 Dimension SIDEBAR_WIDTH_NEGATIVE = -1.0_vp;
73 constexpr static Dimension DEFAULT_SIDE_BAR_WIDTH = 240.0_vp;
74 constexpr Dimension DEFAULT_MIN_SIDE_BAR_WIDTH = 240.0_vp;
75 constexpr Dimension DEFAULT_MAX_SIDE_BAR_WIDTH = 280.0_vp;
76 constexpr int32_t DEFAULT_MIN_CHILDREN_SIZE_WITHOUT_BUTTON_AND_DIVIDER = 1;
77 constexpr static int32_t DEFAULT_CONTROL_BUTTON_ZINDEX = 3;
78 constexpr static int32_t DEFAULT_SIDE_BAR_ZINDEX_EMBED = 0;
79 constexpr static int32_t DEFAULT_DIVIDER_ZINDEX_EMBED = 1;
80 constexpr static int32_t DEFAULT_CONTENT_ZINDEX_EMBED = 2;
81 constexpr static int32_t DEFAULT_SIDE_BAR_ZINDEX_OVERLAY = 2;
82 constexpr static int32_t DEFAULT_DIVIDER_ZINDEX_OVERLAY = 1;
83 constexpr static int32_t DEFAULT_CONTENT_ZINDEX_OVERLAY = 0;
84 constexpr static int32_t DEFAULT_DOUBLE_DRAG_REGION = 2;
85 } // namespace
86 
OnAttachToFrameNode()87 void SideBarContainerPattern::OnAttachToFrameNode()
88 {
89     auto host = GetHost();
90     CHECK_NULL_VOID(host);
91     host->GetRenderContext()->SetClipToBounds(true);
92 
93     auto layoutProperty = host->GetLayoutProperty<SideBarContainerLayoutProperty>();
94     CHECK_NULL_VOID(layoutProperty);
95     userSetSidebarWidth_ = layoutProperty->GetSideBarWidth().value_or(SIDEBAR_WIDTH_NEGATIVE);
96     auto pipelineContext = host->GetContext();
97     CHECK_NULL_VOID(pipelineContext);
98     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
99     auto sideBarTheme = pipelineContext->GetTheme<SideBarTheme>();
100     if (sideBarTheme && sideBarTheme->GetSideBarUnfocusEffectEnable()) {
101         pipelineContext->AddWindowFocusChangedCallback(host->GetId());
102     }
103 }
104 
OnDetachFromFrameNode(FrameNode * frameNode)105 void SideBarContainerPattern::OnDetachFromFrameNode(FrameNode* frameNode)
106 {
107     CHECK_NULL_VOID(frameNode);
108     auto pipeline = frameNode->GetContextWithCheck();
109     CHECK_NULL_VOID(pipeline);
110     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
111     pipeline->RemoveWindowFocusChangedCallback(frameNode->GetId());
112 }
113 
OnUpdateShowSideBar(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty)114 void SideBarContainerPattern::OnUpdateShowSideBar(const RefPtr<SideBarContainerLayoutProperty>& layoutProperty)
115 {
116     CHECK_NULL_VOID(layoutProperty);
117 
118     type_ = layoutProperty->GetSideBarContainerType().value_or(SideBarContainerType::EMBED);
119 
120     if (realSideBarWidth_.IsNegative()) {
121         realSideBarWidth_ = layoutProperty->GetSideBarWidth().value_or(SIDEBAR_WIDTH_NEGATIVE);
122     }
123 
124     auto newShowSideBar = layoutProperty->GetShowSideBar().value_or(true);
125     if (newShowSideBar == userSetShowSideBar_) {
126         return;
127     }
128 
129     if (hasInit_ && ((sideBarStatus_ == SideBarStatus::HIDDEN && newShowSideBar) ||
130         (sideBarStatus_ == SideBarStatus::SHOW && !newShowSideBar))) {
131         FireChangeEvent(newShowSideBar);
132     }
133 
134     userSetShowSideBar_ = newShowSideBar;
135     SetSideBarStatus(newShowSideBar ? SideBarStatus::SHOW : SideBarStatus::HIDDEN);
136     UpdateControlButtonIcon();
137     auto host = GetHost();
138     CHECK_NULL_VOID(host);
139     auto sideBarNode = GetSideBarNode(host);
140     CHECK_NULL_VOID(sideBarNode);
141     if (!newShowSideBar && sideBarNode->IsFirstBuilding()) {
142         SetSideBarActive(false, false);
143     }
144 }
145 
OnUpdateShowControlButton(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & host)146 void SideBarContainerPattern::OnUpdateShowControlButton(
147     const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, const RefPtr<FrameNode>& host)
148 {
149     CHECK_NULL_VOID(layoutProperty);
150     CHECK_NULL_VOID(host);
151 
152     auto showControlButton = layoutProperty->GetShowControlButton().value_or(true);
153 
154     auto children = host->GetChildren();
155     if (children.empty()) {
156         return;
157     }
158 
159     auto controlButtonNode = children.back();
160     if (controlButtonNode->GetTag() != V2::BUTTON_ETS_TAG || !AceType::InstanceOf<FrameNode>(controlButtonNode)) {
161         return;
162     }
163 
164     controlImageWidth_ = layoutProperty->GetControlButtonWidth().value_or(DEFAULT_CONTROL_BUTTON_WIDTH);
165     controlImageHeight_ = layoutProperty->GetControlButtonHeight().value_or(DEFAULT_CONTROL_BUTTON_HEIGHT);
166     auto imageNode = controlButtonNode->GetFirstChild();
167     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
168     if (!imageFrameNode || imageFrameNode ->GetTag() != V2::IMAGE_ETS_TAG) {
169         return;
170     }
171     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
172     CHECK_NULL_VOID(imageLayoutProperty);
173     CalcSize imageCalcSize((CalcLength(controlImageWidth_)), CalcLength(controlImageHeight_));
174     imageLayoutProperty->UpdateUserDefinedIdealSize(imageCalcSize);
175 
176     auto buttonFrameNode = AceType::DynamicCast<FrameNode>(controlButtonNode);
177     auto buttonLayoutProperty = buttonFrameNode->GetLayoutProperty<ButtonLayoutProperty>();
178     CHECK_NULL_VOID(buttonLayoutProperty);
179 
180     buttonLayoutProperty->UpdateVisibility(showControlButton ? VisibleType::VISIBLE : VisibleType::GONE);
181     buttonFrameNode->MarkModifyDone();
182 }
183 
OnUpdateShowDivider(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty,const RefPtr<FrameNode> & host)184 void SideBarContainerPattern::OnUpdateShowDivider(
185     const RefPtr<SideBarContainerLayoutProperty>& layoutProperty, const RefPtr<FrameNode>& host)
186 {
187     CHECK_NULL_VOID(layoutProperty);
188     CHECK_NULL_VOID(host);
189 
190     auto dividerColor = layoutProperty->GetDividerColor().value_or(DEFAULT_DIVIDER_COLOR);
191     auto dividerStrokeWidth = layoutProperty->GetDividerStrokeWidth().value_or(DEFAULT_DIVIDER_STROKE_WIDTH);
192 
193     auto children = host->GetChildren();
194     if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
195         return;
196     }
197 
198     auto begin = children.rbegin();
199     auto dividerNode = *(++begin);
200     CHECK_NULL_VOID(dividerNode);
201     if (dividerNode->GetTag() != V2::DIVIDER_ETS_TAG || !AceType::InstanceOf<FrameNode>(dividerNode)) {
202         return;
203     }
204 
205     auto dividerFrameNode = AceType::DynamicCast<FrameNode>(dividerNode);
206     CHECK_NULL_VOID(dividerFrameNode);
207     auto dividerRenderProperty = dividerFrameNode->GetPaintProperty<DividerRenderProperty>();
208     CHECK_NULL_VOID(dividerRenderProperty);
209     dividerRenderProperty->UpdateDividerColor(dividerColor);
210 
211     auto dividerLayoutProperty = dividerFrameNode->GetLayoutProperty<DividerLayoutProperty>();
212     CHECK_NULL_VOID(dividerLayoutProperty);
213     dividerLayoutProperty->UpdateStrokeWidth(dividerStrokeWidth);
214     dividerFrameNode->MarkModifyDone();
215 }
216 
GetControlImageSize(Dimension & width,Dimension & height)217 void SideBarContainerPattern::GetControlImageSize(Dimension& width, Dimension& height)
218 {
219     auto pipeline = PipelineContext::GetCurrentContext();
220     CHECK_NULL_VOID(pipeline);
221     if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN) {
222         DEFAULT_CONTROL_BUTTON_WIDTH = 24.0_vp;
223         DEFAULT_CONTROL_BUTTON_HEIGHT = 24.0_vp;
224     }
225     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
226     CHECK_NULL_VOID(layoutProperty);
227     controlImageWidth_ = layoutProperty->GetControlButtonWidth().value_or(DEFAULT_CONTROL_BUTTON_WIDTH);
228     controlImageHeight_ = layoutProperty->GetControlButtonHeight().value_or(DEFAULT_CONTROL_BUTTON_HEIGHT);
229 
230     width = controlImageWidth_;
231     height = controlImageHeight_;
232 }
233 
GetContentNode(const RefPtr<FrameNode> & host) const234 RefPtr<FrameNode> SideBarContainerPattern::GetContentNode(const RefPtr<FrameNode>& host) const
235 {
236     CHECK_NULL_RETURN(host, nullptr);
237 
238     const auto& children = host->GetChildren();
239     if (children.size() <= CONTENT_INDEX) {
240         return nullptr;
241     }
242 
243     auto iter = children.rbegin();
244     std::advance(iter, CONTENT_INDEX);
245     auto contentNode = AceType::DynamicCast<FrameNode>(*iter);
246     if (!contentNode) {
247         contentNode = GetFirstFrameNode(*iter);
248     }
249 
250     return contentNode;
251 }
252 
GetSideBarNode(const RefPtr<FrameNode> & host) const253 RefPtr<FrameNode> SideBarContainerPattern::GetSideBarNode(const RefPtr<FrameNode>& host) const
254 {
255     CHECK_NULL_RETURN(host, nullptr);
256 
257     const auto& children = host->GetChildren();
258     if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
259         return nullptr;
260     }
261 
262     auto iter = children.rbegin();
263     std::advance(iter, SIDE_BAR_INDEX);
264     auto sideBarNode = AceType::DynamicCast<FrameNode>(*iter);
265     if (!sideBarNode) {
266         sideBarNode = GetFirstFrameNode(*iter);
267     }
268 
269     return sideBarNode;
270 }
271 
GetFirstFrameNode(const RefPtr<UINode> & host) const272 RefPtr<FrameNode> SideBarContainerPattern::GetFirstFrameNode(const RefPtr<UINode>& host) const
273 {
274     CHECK_NULL_RETURN(host, nullptr);
275     auto children = host->GetChildren();
276     while (!children.empty()) {
277         auto firstChild = children.front();
278         auto firstChildNode = AceType::DynamicCast<FrameNode>(firstChild);
279         if (firstChildNode) {
280             return firstChildNode;
281         }
282         children = firstChild->GetChildren();
283     }
284     TAG_LOGI(AceLogTag::ACE_SIDEBAR, "SideBarContainer can't find child frameNode to set ZIndex");
285     return nullptr;
286 }
287 
GetSideBarNodeOrFirstChild() const288 RefPtr<FrameNode> SideBarContainerPattern::GetSideBarNodeOrFirstChild() const
289 {
290     auto host = GetHost();
291     CHECK_NULL_RETURN(host, nullptr);
292     const auto& children = host->GetChildren();
293     if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
294         return nullptr;
295     }
296 
297     auto iter = children.rbegin();
298     std::advance(iter, SIDE_BAR_INDEX);
299     if (AceType::InstanceOf<NG::CustomNode>(*iter)) {
300         auto sideBarNode = AceType::DynamicCast<CustomNode>(*iter);
301         CHECK_NULL_RETURN(sideBarNode, nullptr);
302         auto sideBarFirstChild = sideBarNode->GetChildren().front();
303         CHECK_NULL_RETURN(sideBarFirstChild, nullptr);
304         auto sideBarFirstChildNode = AceType::DynamicCast<FrameNode>(sideBarFirstChild);
305         CHECK_NULL_RETURN(sideBarFirstChildNode, nullptr);
306         return sideBarFirstChildNode;
307     }
308     auto sideBarNode = AceType::DynamicCast<FrameNode>(*iter);
309     CHECK_NULL_RETURN(sideBarNode, nullptr);
310     return sideBarNode;
311 }
312 
GetControlButtonNode() const313 RefPtr<FrameNode> SideBarContainerPattern::GetControlButtonNode() const
314 {
315     auto host = GetHost();
316     CHECK_NULL_RETURN(host, nullptr);
317     auto children = host->GetChildren();
318     if (children.empty()) {
319         return nullptr;
320     }
321     auto controlButtonNode = children.back();
322     if (controlButtonNode->GetTag() != V2::BUTTON_ETS_TAG || !AceType::InstanceOf<FrameNode>(controlButtonNode)) {
323         return nullptr;
324     }
325     return AceType::DynamicCast<FrameNode>(controlButtonNode);
326 }
327 
GetControlImageNode() const328 RefPtr<FrameNode> SideBarContainerPattern::GetControlImageNode() const
329 {
330     auto host = GetHost();
331     CHECK_NULL_RETURN(host, nullptr);
332 
333     auto children = host->GetChildren();
334     if (children.empty()) {
335         return nullptr;
336     }
337 
338     auto controlButtonNode = children.back();
339     if (controlButtonNode->GetTag() != V2::BUTTON_ETS_TAG || !AceType::InstanceOf<FrameNode>(controlButtonNode)) {
340         return nullptr;
341     }
342 
343     auto buttonChildren = controlButtonNode->GetChildren();
344     if (buttonChildren.empty()) {
345         return nullptr;
346     }
347 
348     auto imageNode = buttonChildren.front();
349     if (imageNode->GetTag() != V2::IMAGE_ETS_TAG || !AceType::InstanceOf<FrameNode>(imageNode)) {
350         return nullptr;
351     }
352     return AceType::DynamicCast<FrameNode>(imageNode);
353 }
354 
GetDividerNode() const355 RefPtr<FrameNode> SideBarContainerPattern::GetDividerNode() const
356 {
357     auto host = GetHost();
358     CHECK_NULL_RETURN(host, nullptr);
359     auto children = host->GetChildren();
360     if (children.size() < DEFAULT_MIN_CHILDREN_SIZE) {
361         return nullptr;
362     }
363 
364     auto begin = children.rbegin();
365     auto dividerNode = *(++begin);
366     CHECK_NULL_RETURN(dividerNode, nullptr);
367     if (dividerNode->GetTag() != V2::DIVIDER_ETS_TAG || !AceType::InstanceOf<FrameNode>(dividerNode)) {
368         return nullptr;
369     }
370 
371     return AceType::DynamicCast<FrameNode>(dividerNode);
372 }
373 
OnUpdateSideBarAndContent(const RefPtr<FrameNode> & host)374 void SideBarContainerPattern::OnUpdateSideBarAndContent(const RefPtr<FrameNode>& host)
375 {
376     CHECK_NULL_VOID(host);
377     auto sideBarNode = GetSideBarNode(host);
378     CHECK_NULL_VOID(sideBarNode);
379     auto sideBarContext = sideBarNode->GetRenderContext();
380     CHECK_NULL_VOID(sideBarContext);
381 
382     if (!sideBarContext->GetClipEdge().has_value() && !sideBarContext->GetClipShape().has_value()) {
383         sideBarContext->SetClipToBounds(true);
384     }
385 
386     auto contentNode = GetContentNode(host);
387     CHECK_NULL_VOID(contentNode);
388     auto contentContext = contentNode->GetRenderContext();
389     CHECK_NULL_VOID(contentContext);
390     if (!contentContext->GetClipEdge().has_value() && !contentContext->GetClipShape().has_value()) {
391         contentContext->SetClipToBounds(true);
392     }
393 }
394 
OnModifyDone()395 void SideBarContainerPattern::OnModifyDone()
396 {
397     Pattern::OnModifyDone();
398 
399     auto host = GetHost();
400     CHECK_NULL_VOID(host);
401 
402     CreateAndMountNodes();
403 
404     auto hub = host->GetEventHub<EventHub>();
405     CHECK_NULL_VOID(hub);
406     auto gestureHub = hub->GetOrCreateGestureEventHub();
407     CHECK_NULL_VOID(gestureHub);
408 
409     InitPanEvent(gestureHub);
410 
411     auto layoutProperty = host->GetLayoutProperty<SideBarContainerLayoutProperty>();
412     OnUpdateShowSideBar(layoutProperty);
413     OnUpdateShowControlButton(layoutProperty, host);
414     OnUpdateShowDivider(layoutProperty, host);
415     UpdateControlButtonIcon();
416 
417     auto pipeline = PipelineContext::GetCurrentContext();
418     CHECK_NULL_VOID(pipeline);
419     if (pipeline->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN) {
420         OnUpdateSideBarAndContent(host);
421     }
422 
423     CHECK_NULL_VOID(layoutProperty);
424     if ((userSetSidebarWidth_ != layoutProperty->GetSideBarWidth().value_or(SIDEBAR_WIDTH_NEGATIVE)) ||
425         (layoutProperty->GetSideBarWidth().value_or(SIDEBAR_WIDTH_NEGATIVE) == DEFAULT_SIDE_BAR_WIDTH)) {
426         preSidebarWidth_.Reset();
427         userSetSidebarWidth_ = layoutProperty->GetSideBarWidth().value_or(SIDEBAR_WIDTH_NEGATIVE);
428     }
429 
430     if (!hasInit_) {
431         hasInit_ = true;
432     }
433 }
434 
CreateAndMountNodes()435 void SideBarContainerPattern::CreateAndMountNodes()
436 {
437     auto host = GetHost();
438     CHECK_NULL_VOID(host);
439 
440     auto children = host->GetChildren();
441     if (children.size() < DEFAULT_MIN_CHILDREN_SIZE_WITHOUT_BUTTON_AND_DIVIDER) {
442         return;
443     }
444 
445     if (HasControlButton()) {
446         UpdateDividerShadow();
447         return;
448     }
449     auto sideBarNode = children.front();
450     sideBarNode->MovePosition(DEFAULT_NODE_SLOT);
451     auto sideBarFrameNode = AceType::DynamicCast<FrameNode>(sideBarNode);
452     if (sideBarFrameNode) {
453         auto renderContext = sideBarFrameNode->GetRenderContext();
454         CHECK_NULL_VOID(renderContext);
455         if (!renderContext->HasBackgroundColor()) {
456             auto context = PipelineBase::GetCurrentContext();
457             CHECK_NULL_VOID(context);
458             auto sideBarTheme = context->GetTheme<SideBarTheme>();
459             CHECK_NULL_VOID(sideBarTheme);
460             Color bgColor = sideBarTheme->GetSideBarBackgroundColor();
461             renderContext->UpdateBackgroundColor(bgColor);
462         }
463         if (SystemProperties::GetSideBarContainerBlurEnable() &&
464             Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
465             !renderContext->GetBackBlurStyle().has_value()) {
466             BlurStyleOption blurStyleOption;
467             blurStyleOption.blurStyle = BlurStyle::COMPONENT_THICK;
468             renderContext->UpdateBackBlurStyle(blurStyleOption);
469         }
470     }
471     host->RebuildRenderContextTree();
472     CreateAndMountDivider(host);
473     CreateAndMountControlButton(host);
474     UpdateDividerShadow();
475 }
476 
UpdateDividerShadow() const477 void SideBarContainerPattern::UpdateDividerShadow() const
478 {
479     auto context = PipelineBase::GetCurrentContext();
480     CHECK_NULL_VOID(context);
481     auto sidebarTheme = context->GetTheme<SideBarTheme>();
482     CHECK_NULL_VOID(sidebarTheme);
483     auto host = GetHost();
484     CHECK_NULL_VOID(host);
485     auto layoutProperty = host->GetLayoutProperty<SideBarContainerLayoutProperty>();
486     CHECK_NULL_VOID(layoutProperty);
487     if (!sidebarTheme->GetDividerShadowEnable()) {
488         return;
489     }
490 
491     auto sideBarContainerType = layoutProperty->GetSideBarContainerType().value_or(SideBarContainerType::EMBED);
492     auto sidebarNode = GetSideBarNode(host);
493     if (sidebarNode) {
494         auto renderContext = sidebarNode->GetRenderContext();
495         renderContext->UpdateZIndex(SideBarContainerType::EMBED == sideBarContainerType
496                                         ? DEFAULT_SIDE_BAR_ZINDEX_EMBED
497                                         : DEFAULT_SIDE_BAR_ZINDEX_OVERLAY);
498     }
499     auto dividerNode = GetDividerNode();
500     if (dividerNode) {
501         auto renderContext = dividerNode->GetRenderContext();
502         renderContext->UpdateZIndex(SideBarContainerType::EMBED == sideBarContainerType
503                                         ? DEFAULT_DIVIDER_ZINDEX_EMBED
504                                         : DEFAULT_DIVIDER_ZINDEX_OVERLAY);
505         renderContext->UpdateBackShadow(ShadowConfig::DefaultShadowXS);
506     }
507     auto contentNode = GetContentNode(host);
508     if (contentNode) {
509         auto renderContext = contentNode->GetRenderContext();
510         renderContext->UpdateZIndex(SideBarContainerType::EMBED == sideBarContainerType
511                                         ? DEFAULT_CONTENT_ZINDEX_EMBED
512                                         : DEFAULT_CONTENT_ZINDEX_OVERLAY);
513     }
514     auto controlBtnNode = GetControlButtonNode();
515     if (controlBtnNode) {
516         auto renderContext = controlBtnNode->GetRenderContext();
517         renderContext->UpdateZIndex(DEFAULT_CONTROL_BUTTON_ZINDEX);
518     }
519 }
520 
SetSideBarActive(bool isActive,bool onlyJsActive) const521 void SideBarContainerPattern::SetSideBarActive(bool isActive, bool onlyJsActive) const
522 {
523     auto host = GetHost();
524     CHECK_NULL_VOID(host);
525     auto sideBarNode = GetSideBarNode(host);
526     CHECK_NULL_VOID(sideBarNode);
527     sideBarNode->SetJSViewActive(isActive);
528     if (!onlyJsActive) {
529         sideBarNode->SetActive(isActive);
530     }
531 }
532 
CreateAndMountDivider(const RefPtr<NG::FrameNode> & parentNode)533 void SideBarContainerPattern::CreateAndMountDivider(const RefPtr<NG::FrameNode>& parentNode)
534 {
535     CHECK_NULL_VOID(parentNode);
536     auto layoutProperty = parentNode->GetLayoutProperty<SideBarContainerLayoutProperty>();
537     CHECK_NULL_VOID(layoutProperty);
538 
539     auto dividerColor = layoutProperty->GetDividerColor().value_or(DEFAULT_DIVIDER_COLOR);
540     auto dividerStrokeWidth = layoutProperty->GetDividerStrokeWidth().value_or(DEFAULT_DIVIDER_STROKE_WIDTH);
541 
542     int32_t dividerNodeId = ElementRegister::GetInstance()->MakeUniqueId();
543     auto dividerNode = FrameNode::GetOrCreateFrameNode(
544         V2::DIVIDER_ETS_TAG, dividerNodeId, []() { return AceType::MakeRefPtr<DividerPattern>(); });
545 
546     auto dividerHub = dividerNode->GetEventHub<EventHub>();
547     CHECK_NULL_VOID(dividerHub);
548     auto inputHub = dividerHub->GetOrCreateInputEventHub();
549     CHECK_NULL_VOID(inputHub);
550     InitDividerMouseEvent(inputHub);
551 
552     auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
553     CHECK_NULL_VOID(dividerRenderProperty);
554     dividerRenderProperty->UpdateDividerColor(dividerColor);
555 
556     auto dividerLayoutProperty = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
557     CHECK_NULL_VOID(dividerLayoutProperty);
558     dividerLayoutProperty->UpdateVertical(true);
559     dividerLayoutProperty->UpdateStrokeWidth(dividerStrokeWidth);
560     auto context = PipelineBase::GetCurrentContext();
561     CHECK_NULL_VOID(context);
562     auto sideBarTheme = context->GetTheme<SideBarTheme>();
563     CHECK_NULL_VOID(sideBarTheme);
564     auto renderContext = dividerNode->GetRenderContext();
565     CHECK_NULL_VOID(renderContext);
566     if (sideBarTheme->GetDividerShadowEnable()) {
567         renderContext->UpdateBackShadow(ShadowConfig::DefaultShadowXS);
568     }
569     renderContext->UpdateZIndex(DEFAULT_DIVIDER_ZINDEX_EMBED);
570     dividerNode->MountToParent(parentNode);
571     dividerNode->MarkModifyDone();
572 }
573 
CreateAndMountControlButton(const RefPtr<NG::FrameNode> & parentNode)574 void SideBarContainerPattern::CreateAndMountControlButton(const RefPtr<NG::FrameNode>& parentNode)
575 {
576     auto context = PipelineBase::GetCurrentContext();
577     CHECK_NULL_VOID(context);
578     auto sideBarTheme = context->GetTheme<SideBarTheme>();
579     CHECK_NULL_VOID(sideBarTheme);
580 
581     auto buttonNode = CreateControlButton(sideBarTheme);
582     CHECK_NULL_VOID(buttonNode);
583     RegisterElementInfoCallBack(buttonNode);
584     auto imgNode = CreateControlImage(sideBarTheme, parentNode);
585     CHECK_NULL_VOID(imgNode);
586 
587     auto buttonHub = buttonNode->GetEventHub<EventHub>();
588     CHECK_NULL_VOID(buttonHub);
589     auto gestureHub = buttonHub->GetOrCreateGestureEventHub();
590     CHECK_NULL_VOID(gestureHub);
591     SetHasControlButton(true);
592     InitControlButtonTouchEvent(gestureHub);
593     InitLongPressEvent(buttonNode);
594 
595     imgNode->MountToParent(buttonNode);
596     buttonNode->MountToParent(parentNode);
597     imgNode->MarkModifyDone();
598     buttonNode->MarkModifyDone();
599 }
600 
CreateControlButton(const RefPtr<SideBarTheme> & sideBarTheme)601 RefPtr<FrameNode> SideBarContainerPattern::CreateControlButton(const RefPtr<SideBarTheme>& sideBarTheme)
602 {
603     int32_t buttonId = ElementRegister::GetInstance()->MakeUniqueId();
604     auto buttonNode = FrameNode::GetOrCreateFrameNode(
605         V2::BUTTON_ETS_TAG, buttonId, []() { return AceType::MakeRefPtr<ButtonPattern>(); });
606     CHECK_NULL_RETURN(buttonNode, nullptr);
607     auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
608     CHECK_NULL_RETURN(buttonLayoutProperty, nullptr);
609     buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
610     auto butttonRadius = sideBarTheme->GetControlButtonRadius();
611     buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(butttonRadius));
612     buttonLayoutProperty->UpdateCreateWithLabel(false);
613     auto buttonRenderContext = buttonNode->GetRenderContext();
614     CHECK_NULL_RETURN(buttonRenderContext, nullptr);
615     buttonRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
616     buttonRenderContext->UpdateZIndex(DEFAULT_CONTROL_BUTTON_ZINDEX);
617     auto focusHub = buttonNode->GetOrCreateFocusHub();
618     CHECK_NULL_RETURN(focusHub, nullptr);
619     focusHub->SetFocusDependence(FocusDependence::SELF);
620     return buttonNode;
621 }
622 
CreateControlImage(const RefPtr<SideBarTheme> & sideBarTheme,const RefPtr<FrameNode> & parentNode)623 RefPtr<FrameNode> SideBarContainerPattern::CreateControlImage(
624     const RefPtr<SideBarTheme>& sideBarTheme, const RefPtr<FrameNode>& parentNode)
625 {
626     int32_t imgNodeId = ElementRegister::GetInstance()->MakeUniqueId();
627     auto imgNode = FrameNode::GetOrCreateFrameNode(
628         V2::IMAGE_ETS_TAG, imgNodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
629     CHECK_NULL_RETURN(imgNode, nullptr);
630 
631     auto layoutProperty = parentNode->GetLayoutProperty<SideBarContainerLayoutProperty>();
632     CHECK_NULL_RETURN(layoutProperty, nullptr);
633     auto isShowSideBar = layoutProperty->GetShowSideBar().value_or(true);
634     std::optional<ImageSourceInfo> info = std::nullopt;
635     if (isShowSideBar) {
636         info = layoutProperty->GetControlButtonShowIconInfo();
637     } else {
638         info = layoutProperty->GetControlButtonHiddenIconInfo();
639     }
640     if (!info.has_value()) {
641         info = std::make_optional<ImageSourceInfo>();
642         info->SetResourceId(InternalResource::ResourceId::SIDE_BAR);
643         Color controlButtonColor = sideBarTheme->GetControlImageColor();
644         info->SetFillColor(controlButtonColor);
645     }
646     imageInfo_ = info.value();
647     auto imageLayoutProperty = imgNode->GetLayoutProperty<ImageLayoutProperty>();
648     CHECK_NULL_RETURN(imageLayoutProperty, nullptr);
649     imageLayoutProperty->UpdateImageSourceInfo(info.value());
650     imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
651     imageLayoutProperty->UpdateAlignment(Alignment::CENTER);
652     Dimension imageWidth;
653     Dimension imageHeight;
654     GetControlImageSize(imageWidth, imageHeight);
655     CalcSize imageCalcSize((CalcLength(imageWidth)), CalcLength(imageHeight));
656     imageLayoutProperty->UpdateUserDefinedIdealSize(imageCalcSize);
657     InitImageErrorCallback(sideBarTheme, imgNode);
658     return imgNode;
659 }
660 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)661 void SideBarContainerPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
662 {
663     CHECK_NULL_VOID(!dragEvent_);
664 
665     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
666         auto pattern = weak.Upgrade();
667         CHECK_NULL_VOID(pattern);
668         pattern->HandleDragStart();
669     };
670 
671     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
672         auto pattern = weak.Upgrade();
673         CHECK_NULL_VOID(pattern);
674         pattern->HandleDragUpdate(static_cast<float>(info.GetOffsetX()));
675     };
676 
677     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
678         auto pattern = weak.Upgrade();
679         CHECK_NULL_VOID(pattern);
680         pattern->HandleDragEnd();
681     };
682 
683     auto actionCancelTask = [weak = WeakClaim(this)]() {
684         auto pattern = weak.Upgrade();
685         CHECK_NULL_VOID(pattern);
686         pattern->HandleDragEnd();
687     };
688 
689     dragEvent_ = MakeRefPtr<PanEvent>(
690         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
691     PanDirection panDirection = { .type = PanDirection::HORIZONTAL };
692 
693     auto dividerNode = GetDividerNode();
694     CHECK_NULL_VOID(dividerNode);
695     auto dividerGestureHub = dividerNode->GetOrCreateGestureEventHub();
696     CHECK_NULL_VOID(dividerGestureHub);
697     dividerGestureHub->AddPanEvent(dragEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
698 }
699 
CreateAnimation()700 void SideBarContainerPattern::CreateAnimation()
701 {
702     auto host = GetHost();
703     CHECK_NULL_VOID(host);
704 
705     if (!controller_) {
706         controller_ = CREATE_ANIMATOR(host->GetContextRefPtr());
707     }
708 
709     auto weak = AceType::WeakClaim(this);
710     if (!rightToLeftAnimation_) {
711         rightToLeftAnimation_ =
712             AceType::MakeRefPtr<CurveAnimation<float>>(RATIO_ZERO, RATIO_NEGATIVE, Curves::FRICTION);
713         rightToLeftAnimation_->AddListener(Animation<float>::ValueCallback([weak](float value) {
714             auto pattern = weak.Upgrade();
715             if (pattern) {
716                 pattern->UpdateSideBarPosition(value);
717             }
718         }));
719     }
720 
721     if (!leftToRightAnimation_) {
722         leftToRightAnimation_ =
723             AceType::MakeRefPtr<CurveAnimation<float>>(RATIO_NEGATIVE, RATIO_ZERO, Curves::FRICTION);
724         leftToRightAnimation_->AddListener(Animation<float>::ValueCallback([weak](float value) {
725             auto pattern = weak.Upgrade();
726             if (pattern) {
727                 pattern->UpdateSideBarPosition(value);
728             }
729         }));
730     }
731 }
732 
InitControlButtonTouchEvent(const RefPtr<GestureEventHub> & gestureHub)733 void SideBarContainerPattern::InitControlButtonTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
734 {
735     CHECK_NULL_VOID(!controlButtonClickEvent_);
736 
737     auto clickTask = [weak = WeakClaim(this)](const GestureEvent& info) {
738         auto pattern = weak.Upgrade();
739         CHECK_NULL_VOID(pattern);
740         if (!pattern->inAnimation_) {
741             pattern->SetControlButtonClick(true);
742             pattern->DoAnimation();
743         }
744     };
745     controlButtonClickEvent_ = MakeRefPtr<ClickEvent>(std::move(clickTask));
746     gestureHub->AddClickEvent(controlButtonClickEvent_);
747 }
748 
UpdateAnimDir()749 void SideBarContainerPattern::UpdateAnimDir()
750 {
751     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
752     CHECK_NULL_VOID(layoutProperty);
753     auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
754 
755     switch (sideBarStatus_) {
756         case SideBarStatus::HIDDEN:
757             if (sideBarPosition == SideBarPosition::START) {
758                 animDir_ = SideBarAnimationDirection::LTR;
759             } else {
760                 animDir_ = SideBarAnimationDirection::RTL;
761             }
762             break;
763         case SideBarStatus::SHOW:
764             if (sideBarPosition == SideBarPosition::START) {
765                 animDir_ = SideBarAnimationDirection::RTL;
766             } else {
767                 animDir_ = SideBarAnimationDirection::LTR;
768             }
769             break;
770         default:
771             break;
772     }
773 }
774 
DoAnimation()775 void SideBarContainerPattern::DoAnimation()
776 {
777     auto host = GetHost();
778     CHECK_NULL_VOID(host);
779 
780     if (autoHide_) {
781         sideBarStatus_ = SideBarStatus::HIDDEN;
782     }
783 
784     SetSideBarActive(true, false);
785     UpdateAnimDir();
786 
787     AnimationOption option = AnimationOption();
788     option.SetDuration(SIDEBAR_DURATION);
789     option.SetCurve(SIDEBAR_CURVE);
790     option.SetFillMode(FillMode::FORWARDS);
791 
792     auto sideBarStatus = sideBarStatus_;
793     sideBarStatus_ = SideBarStatus::CHANGING;
794     UpdateControlButtonIcon();
795 
796     // fire before animation to include user changes in onChange event
797     FireChangeEvent(sideBarStatus == SideBarStatus::HIDDEN);
798 
799     auto weak = AceType::WeakClaim(this);
800     auto context = PipelineContext::GetCurrentContext();
801     inAnimation_ = true;
802     context->OpenImplicitAnimation(option, option.GetCurve(), [weak, sideBarStatus]() {
803         auto pattern = weak.Upgrade();
804         if (pattern) {
805             if (sideBarStatus == SideBarStatus::HIDDEN) {
806                 pattern->SetSideBarStatus(SideBarStatus::SHOW);
807                 pattern->UpdateControlButtonIcon();
808             } else {
809                 pattern->SetSideBarStatus(SideBarStatus::HIDDEN);
810                 pattern->UpdateControlButtonIcon();
811                 pattern->SetSideBarActive(false, false);
812             }
813             pattern->inAnimation_ = false;
814         }
815     });
816 
817     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
818     CHECK_NULL_VOID(layoutProperty);
819     auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
820     auto realSideBarWidthPx = DimensionConvertToPx(realSideBarWidth_).value_or(0.0);
821     if (sideBarPosition == SideBarPosition::START) {
822         if (animDir_ == SideBarAnimationDirection::LTR) {
823             currentOffset_ = 0.0f;
824         } else {
825             currentOffset_ = -realSideBarWidthPx - realDividerWidth_;
826         }
827     } else {
828         if (animDir_ == SideBarAnimationDirection::LTR) {
829             currentOffset_ = 0.0f + realDividerWidth_;
830         } else {
831             currentOffset_ = -realSideBarWidthPx;
832         }
833     }
834 
835     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
836     context->FlushUITasks();
837     context->CloseImplicitAnimation();
838 }
839 
HandlePanEventEnd()840 void SideBarContainerPattern::HandlePanEventEnd()
841 {
842     if (sideBarStatus_ == SideBarStatus::HIDDEN) {
843         DoAnimation();
844     }
845 }
846 
UpdateSideBarPosition(float value)847 void SideBarContainerPattern::UpdateSideBarPosition(float value)
848 {
849     auto host = GetHost();
850     CHECK_NULL_VOID(host);
851 
852     if (sideBarStatus_ != SideBarStatus::CHANGING) {
853         sideBarStatus_ = SideBarStatus::CHANGING;
854         UpdateControlButtonIcon();
855     }
856 
857     auto realSideBarWidthPx = DimensionConvertToPx(realSideBarWidth_).value_or(0.0);
858     currentOffset_ = value * (realSideBarWidthPx + realDividerWidth_);
859     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
860 }
861 
FireChangeEvent(bool isShow)862 void SideBarContainerPattern::FireChangeEvent(bool isShow)
863 {
864     auto sideBarContainerEventHub = GetEventHub<SideBarContainerEventHub>();
865     CHECK_NULL_VOID(sideBarContainerEventHub);
866 
867     sideBarContainerEventHub->FireChangeEvent(isShow);
868 
869     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
870         Recorder::EventParamsBuilder builder;
871         auto host = GetHost();
872         CHECK_NULL_VOID(host);
873         auto inspectorId = host->GetInspectorId().value_or("");
874         builder.SetId(inspectorId)
875             .SetType(host->GetTag())
876             .SetChecked(isShow)
877             .SetDescription(host->GetAutoEventParamValue(""));
878         Recorder::EventRecorder::Get().OnChange(std::move(builder));
879     }
880 }
881 
UpdateControlButtonIcon()882 void SideBarContainerPattern::UpdateControlButtonIcon()
883 {
884     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
885     CHECK_NULL_VOID(layoutProperty);
886 
887     auto imgFrameNode = GetControlImageNode();
888     CHECK_NULL_VOID(imgFrameNode);
889 
890     auto imgRenderContext = imgFrameNode->GetRenderContext();
891     auto imageLayoutProperty = imgFrameNode->GetLayoutProperty<ImageLayoutProperty>();
892     CHECK_NULL_VOID(imageLayoutProperty);
893     std::optional<ImageSourceInfo> imgSourceInfo = std::nullopt;
894 
895     auto context = PipelineBase::GetCurrentContext();
896     CHECK_NULL_VOID(context);
897     auto sideBarTheme = context->GetTheme<SideBarTheme>();
898     CHECK_NULL_VOID(sideBarTheme);
899     Color controlButtonColor = sideBarTheme->GetControlImageColor();
900 
901     switch (sideBarStatus_) {
902         case SideBarStatus::SHOW:
903             imgSourceInfo = layoutProperty->GetControlButtonShowIconInfo();
904             break;
905         case SideBarStatus::HIDDEN:
906             imgSourceInfo = layoutProperty->GetControlButtonHiddenIconInfo();
907             break;
908         case SideBarStatus::CHANGING:
909             imgSourceInfo = layoutProperty->GetControlButtonSwitchingIconInfo();
910             break;
911         default:
912             break;
913     }
914 
915     if (!imgSourceInfo.has_value()) {
916         imgSourceInfo = std::make_optional<ImageSourceInfo>();
917         imgSourceInfo->SetResourceId(InternalResource::ResourceId::SIDE_BAR);
918         imgSourceInfo->SetFillColor(controlButtonColor);
919     }
920     imageInfo_ = imgSourceInfo.value();
921     imageLayoutProperty->UpdateImageSourceInfo(imgSourceInfo.value());
922     imgFrameNode->MarkModifyDone();
923 }
924 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)925 bool SideBarContainerPattern::OnDirtyLayoutWrapperSwap(
926     const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
927 {
928     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
929     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
930     auto layoutAlgorithm = DynamicCast<SideBarContainerLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
931     CHECK_NULL_RETURN(layoutAlgorithm, false);
932 
933     realDividerWidth_ = layoutAlgorithm->GetRealDividerWidth();
934     realSideBarWidth_ = layoutAlgorithm->GetRealSideBarWidth();
935     realSideBarHeight_ = layoutAlgorithm->GetRealSideBarHeight();
936     AddDividerHotZoneRect(layoutAlgorithm);
937 
938     if (needInitRealSideBarWidth_) {
939         needInitRealSideBarWidth_ = false;
940     }
941 
942     if (isControlButtonClick_) {
943         isControlButtonClick_ = false;
944     }
945 
946     if (autoHide_ != layoutAlgorithm->GetAutoHide()) {
947         FireChangeEvent(layoutAlgorithm->GetSideBarStatus() == SideBarStatus::SHOW);
948     }
949 
950     if (!inAnimation_) {
951         SetSideBarActive(layoutAlgorithm->GetSideBarStatus() == SideBarStatus::SHOW, true);
952     }
953 
954     adjustMaxSideBarWidth_ = layoutAlgorithm->GetAdjustMaxSideBarWidth();
955     adjustMinSideBarWidth_ = layoutAlgorithm->GetAdjustMinSideBarWidth();
956     type_ = layoutAlgorithm->GetSideBarContainerType();
957     autoHide_ = layoutAlgorithm->GetAutoHide();
958 
959     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
960     CHECK_NULL_RETURN(layoutProperty, false);
961     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
962     return paddingProperty != nullptr;
963 }
964 
AddDividerHotZoneRect(const RefPtr<SideBarContainerLayoutAlgorithm> & layoutAlgorithm)965 void SideBarContainerPattern::AddDividerHotZoneRect(const RefPtr<SideBarContainerLayoutAlgorithm>& layoutAlgorithm)
966 {
967     CHECK_NULL_VOID(layoutAlgorithm);
968     if (realDividerWidth_ < 0.0f) {
969         return;
970     }
971 
972     auto dividerFrameNode = GetDividerNode();
973     CHECK_NULL_VOID(dividerFrameNode);
974     auto geometryNode = dividerFrameNode->GetGeometryNode();
975     CHECK_NULL_VOID(geometryNode);
976     auto dividerHeight = geometryNode->GetFrameSize().Height();
977     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
978     CHECK_NULL_VOID(layoutProperty);
979 
980     OffsetF hotZoneOffset;
981     hotZoneOffset.SetX(-DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_VP.ConvertToPx());
982     SizeF hotZoneSize;
983     auto baseWidth = NearZero(realDividerWidth_, 0.0f) ?
984         DEFAULT_DIVIDER_STROKE_WIDTH.ConvertToPx() : realDividerWidth_;
985     hotZoneSize.SetWidth(baseWidth + DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_VALUE *
986                                                  DEFAULT_DIVIDER_HOT_ZONE_HORIZONTAL_PADDING_VP.ConvertToPx());
987     hotZoneSize.SetHeight(dividerHeight);
988 
989     DimensionRect hotZoneRegion;
990     hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize.Width()), Dimension(hotZoneSize.Height())));
991     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset.GetX()), Dimension(hotZoneOffset.GetY())));
992 
993     std::vector<DimensionRect> mouseRegion;
994     mouseRegion.emplace_back(hotZoneRegion);
995 
996     dividerFrameNode->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
997     auto dividerGestureHub = dividerFrameNode->GetOrCreateGestureEventHub();
998     CHECK_NULL_VOID(dividerGestureHub);
999     dividerGestureHub->SetMouseResponseRegion(mouseRegion);
1000 
1001     auto dragRectOffset = layoutAlgorithm->GetSideBarOffset();
1002     dragRectOffset.SetX(-DEFAULT_DRAG_REGION.ConvertToPx());
1003     dragRect_.SetOffset(dragRectOffset);
1004 
1005     // divider drag rect height = dividerHeight - divider start margin - divider end margin
1006     dragRect_.SetSize(SizeF(DEFAULT_DRAG_REGION.ConvertToPx() * DEFAULT_DOUBLE_DRAG_REGION + realDividerWidth_,
1007         dividerHeight));
1008 
1009     std::vector<DimensionRect> responseRegion;
1010     DimensionOffset responseOffset(dragRectOffset);
1011     DimensionRect responseRect(Dimension(dragRect_.Width(), DimensionUnit::PX),
1012         Dimension(dragRect_.Height(), DimensionUnit::PX), responseOffset);
1013     responseRegion.emplace_back(responseRect);
1014     dividerGestureHub->SetResponseRegion(responseRegion);
1015 }
1016 
HandleDragStart()1017 void SideBarContainerPattern::HandleDragStart()
1018 {
1019     if (!isDividerDraggable_ || sideBarStatus_ != SideBarStatus::SHOW) {
1020         return;
1021     }
1022     isInDividerDrag_ = true;
1023     auto pipeline = PipelineContext::GetCurrentContext();
1024     CHECK_NULL_VOID(pipeline);
1025     auto windowId = pipeline->GetWindowId();
1026     auto mouseStyle = MouseStyle::CreateMouseStyle();
1027     mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), MouseFormat::RESIZE_LEFT_RIGHT);
1028     preSidebarWidth_ = realSideBarWidth_;
1029 }
1030 
HandleDragUpdate(float xOffset)1031 void SideBarContainerPattern::HandleDragUpdate(float xOffset)
1032 {
1033     if (sideBarStatus_ != SideBarStatus::SHOW) {
1034         return;
1035     }
1036 
1037     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
1038     CHECK_NULL_VOID(layoutProperty);
1039 
1040     auto host = GetHost();
1041     CHECK_NULL_VOID(host);
1042     auto pipeline = PipelineContext::GetCurrentContext();
1043     CHECK_NULL_VOID(pipeline);
1044     if (pipeline->GetMinPlatformVersion() < PLATFORM_VERSION_TEN) {
1045         auto geometryNode = host->GetGeometryNode();
1046         CHECK_NULL_VOID(geometryNode);
1047 
1048         auto frameSize = geometryNode->GetFrameSize();
1049         auto parentWidth = frameSize.Width();
1050         auto constraint = layoutProperty->GetLayoutConstraint();
1051         auto scaleProperty = constraint->scaleProperty;
1052         minSideBarWidth_ = ConvertToPx(adjustMinSideBarWidth_, scaleProperty, parentWidth).value_or(0);
1053         maxSideBarWidth_ = ConvertToPx(adjustMaxSideBarWidth_, scaleProperty, parentWidth).value_or(0);
1054     }
1055 
1056     auto sideBarPosition = GetSideBarPositionWithRtl(layoutProperty);
1057     bool isSideBarStart = sideBarPosition == SideBarPosition::START;
1058 
1059     bool isPercent = realSideBarWidth_.Unit() == DimensionUnit::PERCENT;
1060     auto preSidebarWidthPx = DimensionConvertToPx(preSidebarWidth_).value_or(0.0);
1061     auto sideBarLine = preSidebarWidthPx + (isSideBarStart ? xOffset : -xOffset);
1062 
1063     if (sideBarLine > minSideBarWidth_ && sideBarLine < maxSideBarWidth_) {
1064         realSideBarWidth_ = isPercent ? ConvertPxToPercent(sideBarLine) : Dimension(sideBarLine, DimensionUnit::PX);
1065         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1066         return;
1067     }
1068 
1069     if (sideBarLine >= maxSideBarWidth_) {
1070         realSideBarWidth_ =
1071             isPercent ? ConvertPxToPercent(maxSideBarWidth_) : Dimension(maxSideBarWidth_, DimensionUnit::PX);
1072         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1073         return;
1074     }
1075 
1076     auto halfDragRegionWidth = dragRect_.Width() / 2;
1077     if (sideBarLine > minSideBarWidth_ - halfDragRegionWidth) {
1078         realSideBarWidth_ =
1079             isPercent ? ConvertPxToPercent(minSideBarWidth_) : Dimension(minSideBarWidth_, DimensionUnit::PX);
1080         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1081         return;
1082     }
1083     realSideBarWidth_ =
1084         isPercent ? ConvertPxToPercent(minSideBarWidth_) : Dimension(minSideBarWidth_, DimensionUnit::PX);
1085 
1086     auto autoHideProperty = layoutProperty->GetAutoHide().value_or(true);
1087     if (autoHideProperty) {
1088         DoAnimation();
1089     }
1090 }
1091 
HandleDragEnd()1092 void SideBarContainerPattern::HandleDragEnd()
1093 {
1094     isInDividerDrag_ = false;
1095     auto pipeline = PipelineContext::GetCurrentContext();
1096     CHECK_NULL_VOID(pipeline);
1097     auto windowId = pipeline->GetWindowId();
1098     auto mouseStyle = MouseStyle::CreateMouseStyle();
1099     mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), MouseFormat::DEFAULT);
1100     if (!isDividerDraggable_ || sideBarStatus_ != SideBarStatus::SHOW) {
1101         return;
1102     }
1103     preSidebarWidth_ = realSideBarWidth_;
1104 }
1105 
InitDividerMouseEvent(const RefPtr<InputEventHub> & inputHub)1106 void SideBarContainerPattern::InitDividerMouseEvent(const RefPtr<InputEventHub>& inputHub)
1107 {
1108     CHECK_NULL_VOID(inputHub);
1109     CHECK_NULL_VOID(!hoverEvent_);
1110 
1111     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1112         CHECK_NULL_VOID(!dividerMouseEvent_);
1113         auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
1114             auto pattern = weak.Upgrade();
1115             if (pattern) {
1116                 pattern->OnDividerMouseEvent(info);
1117             }
1118         };
1119         dividerMouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
1120         inputHub->AddOnMouseEvent(dividerMouseEvent_);
1121     }
1122 
1123     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
1124         auto pattern = weak.Upgrade();
1125         if (pattern) {
1126             pattern->OnHover(isHover);
1127         }
1128     };
1129     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
1130     inputHub->AddOnHoverEvent(hoverEvent_);
1131 }
1132 
OnDividerMouseEvent(MouseInfo & info)1133 void SideBarContainerPattern::OnDividerMouseEvent(MouseInfo& info)
1134 {
1135     // release the mouse button, to check if still in the divider's region
1136     if (info.GetAction() != MouseAction::RELEASE) {
1137         return;
1138     }
1139     auto pipeline = PipelineContext::GetCurrentContext();
1140     CHECK_NULL_VOID(pipeline);
1141     auto dividerFrameNode = GetDividerNode();
1142     CHECK_NULL_VOID(dividerFrameNode);
1143     auto defaultRect = RectF();
1144     auto responseMouseRegionList = dividerFrameNode->GetResponseRegionList(defaultRect,
1145         static_cast<int32_t>(SourceType::MOUSE));
1146     auto localParentPoint = PointF(static_cast<float>(info.GetLocalLocation().GetX()),
1147         static_cast<float>(info.GetLocalLocation().GetY()));
1148 
1149     if (dividerFrameNode->InResponseRegionList(localParentPoint, responseMouseRegionList)) {
1150         return;
1151     }
1152     TAG_LOGI(AceLogTag::ACE_SIDEBAR, "sideBarContainer Divider is out of region.");
1153     MouseFormat format = MouseFormat::DEFAULT;
1154     auto windowId = pipeline->GetWindowId();
1155     auto mouseStyle = MouseStyle::CreateMouseStyle();
1156     int32_t currentPointerStyle = 0;
1157     mouseStyle->GetPointerStyle(static_cast<int32_t>(windowId), currentPointerStyle);
1158     if (currentPointerStyle != static_cast<int32_t>(format)) {
1159         mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), format);
1160     }
1161 }
1162 
OnHover(bool isHover)1163 void SideBarContainerPattern::OnHover(bool isHover)
1164 {
1165     if (isInDividerDrag_) {
1166         return;
1167     }
1168     TAG_LOGD(AceLogTag::ACE_SIDEBAR, "sideBarContainer onHover");
1169     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
1170     CHECK_NULL_VOID(layoutProperty);
1171     auto dividerStrokeWidth = layoutProperty->GetDividerStrokeWidth().value_or(DEFAULT_DIVIDER_STROKE_WIDTH);
1172     auto minSideBarWidth = layoutProperty->GetMinSideBarWidthValue(DEFAULT_MIN_SIDE_BAR_WIDTH);
1173     auto maxSideBarWidth = layoutProperty->GetMaxSideBarWidthValue(DEFAULT_MAX_SIDE_BAR_WIDTH);
1174     if (Negative(dividerStrokeWidth.Value()) || GreatOrEqual(minSideBarWidth.Value(), maxSideBarWidth.Value())) {
1175         isDividerDraggable_ = false;
1176         return;
1177     }
1178     isDividerDraggable_ = true;
1179 
1180     MouseFormat format = isHover ? MouseFormat::RESIZE_LEFT_RIGHT : MouseFormat::DEFAULT;
1181     auto pipeline = PipelineContext::GetCurrentContext();
1182     CHECK_NULL_VOID(pipeline);
1183     auto windowId = pipeline->GetWindowId();
1184     auto mouseStyle = MouseStyle::CreateMouseStyle();
1185     int32_t currentPointerStyle = 0;
1186     mouseStyle->GetPointerStyle(static_cast<int32_t>(windowId), currentPointerStyle);
1187     if (currentPointerStyle != static_cast<int32_t>(format) && sideBarStatus_ == SideBarStatus::SHOW) {
1188         mouseStyle->SetPointerStyle(static_cast<int32_t>(windowId), format);
1189     }
1190 }
1191 
GetSideBarPositionWithRtl(const RefPtr<SideBarContainerLayoutProperty> & layoutProperty)1192 SideBarPosition SideBarContainerPattern::GetSideBarPositionWithRtl(
1193     const RefPtr<SideBarContainerLayoutProperty>& layoutProperty)
1194 {
1195     auto sideBarPosition = layoutProperty->GetSideBarPosition().value_or(SideBarPosition::START);
1196     if (layoutProperty->GetLayoutDirection() == TextDirection::RTL ||
1197         AceApplicationInfo::GetInstance().IsRightToLeft()) {
1198         sideBarPosition = (sideBarPosition == SideBarPosition::START) ? SideBarPosition::END : SideBarPosition::START;
1199     }
1200     return sideBarPosition;
1201 }
1202 
OnLanguageConfigurationUpdate()1203 void SideBarContainerPattern::OnLanguageConfigurationUpdate()
1204 {
1205     auto host = GetHost();
1206     CHECK_NULL_VOID(host);
1207     if (isRightToLeft_ != AceApplicationInfo::GetInstance().IsRightToLeft()) {
1208         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1209         isRightToLeft_ = AceApplicationInfo::GetInstance().IsRightToLeft();
1210     }
1211 }
1212 
CreateNodePaintMethod()1213 RefPtr<NodePaintMethod> SideBarContainerPattern::CreateNodePaintMethod()
1214 {
1215     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
1216     CHECK_NULL_RETURN(layoutProperty, nullptr);
1217     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
1218     bool needClipPadding = paddingProperty != nullptr;
1219     auto paintMethod = MakeRefPtr<SideBarContainerPaintMethod>();
1220     paintMethod->SetNeedClipPadding(needClipPadding);
1221     return paintMethod;
1222 }
1223 
DimensionConvertToPx(const Dimension & value) const1224 std::optional<float> SideBarContainerPattern::DimensionConvertToPx(const Dimension& value) const
1225 {
1226     auto host = GetHost();
1227     CHECK_NULL_RETURN(host, std::nullopt);
1228     auto geometryNode = host->GetGeometryNode();
1229     CHECK_NULL_RETURN(geometryNode, std::nullopt);
1230     auto frameSize = geometryNode->GetFrameSize();
1231     auto parentWidth = frameSize.Width();
1232     auto layoutProperty = GetLayoutProperty<SideBarContainerLayoutProperty>();
1233     CHECK_NULL_RETURN(layoutProperty, std::nullopt);
1234     auto constraint = layoutProperty->GetLayoutConstraint();
1235     auto scaleProperty = constraint->scaleProperty;
1236     return ConvertToPx(value, scaleProperty, parentWidth);
1237 }
1238 
ConvertPxToPercent(float value) const1239 Dimension SideBarContainerPattern::ConvertPxToPercent(float value) const
1240 {
1241     auto result = Dimension(0.0, DimensionUnit::PERCENT);
1242     auto host = GetHost();
1243     CHECK_NULL_RETURN(host, result);
1244     auto geometryNode = host->GetGeometryNode();
1245     CHECK_NULL_RETURN(geometryNode, result);
1246 
1247     auto frameSize = geometryNode->GetFrameSize();
1248     auto parentWidth = frameSize.Width();
1249     if (!NearZero(parentWidth)) {
1250         result = Dimension(value / parentWidth, DimensionUnit::PERCENT);
1251     }
1252 
1253     return result;
1254 }
1255 
WindowFocus(bool isFocus)1256 void SideBarContainerPattern::WindowFocus(bool isFocus)
1257 {
1258     isWindowFocus_ = isFocus;
1259     SetSideBarMask(isFocus);
1260 }
1261 
OnColorConfigurationUpdate()1262 void SideBarContainerPattern::OnColorConfigurationUpdate()
1263 {
1264     SetSideBarMask(isWindowFocus_);
1265 }
1266 
SetSideBarMask(bool isWindowFocus) const1267 void SideBarContainerPattern::SetSideBarMask(bool isWindowFocus) const
1268 {
1269     auto context = PipelineBase::GetCurrentContext();
1270     CHECK_NULL_VOID(context);
1271     auto sideBarTheme = context->GetTheme<SideBarTheme>();
1272     CHECK_NULL_VOID(sideBarTheme);
1273     auto sideBarNode = GetSideBarNodeOrFirstChild();
1274     CHECK_NULL_VOID(sideBarNode);
1275 
1276     Color maskColor = sideBarTheme->GetSideBarUnfocusColor().BlendOpacity(DEFAULT_SIDE_BAR_MASK_OPACITY);
1277     auto maskProperty = AceType::MakeRefPtr<ProgressMaskProperty>();
1278     maskProperty->SetColor((!isWindowFocus && sideBarNode->IsVisible()) ? maskColor : Color::TRANSPARENT);
1279 
1280     auto sideBarRenderContext = sideBarNode->GetRenderContext();
1281     CHECK_NULL_VOID(sideBarRenderContext);
1282     sideBarRenderContext->UpdateProgressMask(maskProperty);
1283 
1284     auto buttonNode = GetControlButtonNode();
1285     CHECK_NULL_VOID(buttonNode);
1286     auto buttonRenderContext = buttonNode->GetRenderContext();
1287     CHECK_NULL_VOID(buttonRenderContext);
1288     buttonRenderContext->UpdateProgressMask(maskProperty);
1289 }
1290 
InitLongPressEvent(const RefPtr<FrameNode> & buttonNode)1291 void SideBarContainerPattern::InitLongPressEvent(const RefPtr<FrameNode>& buttonNode)
1292 {
1293     if (longPressEvent_) {
1294         return;
1295     }
1296 
1297     auto buttonHub = buttonNode->GetEventHub<EventHub>();
1298     CHECK_NULL_VOID(buttonHub);
1299     auto gestureHub = buttonHub->GetOrCreateGestureEventHub();
1300     CHECK_NULL_VOID(gestureHub);
1301 
1302     auto longPressTask = [weak = WeakClaim(this)](GestureEvent& info) {
1303         auto pattern = weak.Upgrade();
1304         if (pattern) {
1305             pattern->HandleLongPressEvent();
1306         }
1307     };
1308     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressTask));
1309     gestureHub->SetLongPressEvent(longPressEvent_, false, false);
1310 
1311     auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
1312     CHECK_NULL_VOID(longPressRecognizer);
1313     if (!longPressActionEnd_) {
1314         auto longPressActionEnd = [weak = WeakClaim(this)] (GestureEvent& info) {
1315             auto pattern = weak.Upgrade();
1316             CHECK_NULL_VOID(pattern);
1317             pattern->HandleLongPressActionEnd();
1318         };
1319         longPressActionEnd_ = longPressActionEnd;
1320     }
1321     longPressRecognizer->SetOnActionEnd(longPressActionEnd_);
1322 }
1323 
HandleLongPressEvent()1324 void SideBarContainerPattern::HandleLongPressEvent()
1325 {
1326     auto pipeline = PipelineContext::GetCurrentContext();
1327     CHECK_NULL_VOID(pipeline);
1328     float scale = pipeline->GetFontScale();
1329     if (LessNotEqual(scale, AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
1330         return;
1331     }
1332     ShowDialogWithNode();
1333 }
1334 
HandleLongPressActionEnd()1335 void SideBarContainerPattern::HandleLongPressActionEnd()
1336 {
1337     if (!isDialogShow_) {
1338         return;
1339     }
1340     auto pipeline = PipelineContext::GetCurrentContext();
1341     CHECK_NULL_VOID(pipeline);
1342     auto overlayManager = pipeline->GetOverlayManager();
1343     CHECK_NULL_VOID(overlayManager);
1344     overlayManager->CloseDialog(dialogNode_);
1345     dialogNode_ = nullptr;
1346     isDialogShow_ = false;
1347 }
1348 
ShowDialogWithNode()1349 void SideBarContainerPattern::ShowDialogWithNode()
1350 {
1351     if (isDialogShow_) {
1352         return;
1353     }
1354     auto host = GetHost();
1355     CHECK_NULL_VOID(host);
1356     auto buttonNode = DynamicCast<FrameNode>(host->GetLastChild());
1357     CHECK_NULL_VOID(buttonNode);
1358     auto accessibilityProperty = buttonNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1359     CHECK_NULL_VOID(accessibilityProperty);
1360     auto text = accessibilityProperty->GetAccessibilityText();
1361 
1362     dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(text, imageInfo_);
1363 
1364     isDialogShow_ = true;
1365 }
1366 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1367 void SideBarContainerPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1368 {
1369     TAG_LOGI(AceLogTag::ACE_SIDEBAR, "mark need retrieve sidebar property because of window rotation or resize");
1370     MarkNeedInitRealSideBarWidth(true);
1371 }
1372 
RegisterElementInfoCallBack(const RefPtr<FrameNode> & buttonNode)1373 void SideBarContainerPattern::RegisterElementInfoCallBack(const RefPtr<FrameNode>& buttonNode)
1374 {
1375 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
1376     CHECK_NULL_VOID(buttonNode);
1377     auto accessibilityProperty = buttonNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
1378     CHECK_NULL_VOID(accessibilityProperty);
1379     auto callBack = [weak = WeakClaim(this)] (Accessibility::ExtraElementInfo& extraElementInfo) {
1380         auto pattern = weak.Upgrade();
1381         CHECK_NULL_VOID(pattern);
1382         auto showSideBar = pattern->GetShowSideBar();
1383         extraElementInfo.SetExtraElementInfo(
1384             "SideBarContainerStates", static_cast<int32_t>(showSideBar));
1385     };
1386     accessibilityProperty->SetRelatedElementInfoCallback(callBack);
1387 #endif
1388 }
1389 
SetAccessibilityEvent()1390 void SideBarContainerPattern::SetAccessibilityEvent()
1391 {
1392     auto controlButton = GetControlButtonNode();
1393     CHECK_NULL_VOID(controlButton);
1394     // use TEXT_CHANGE event to report information update
1395     controlButton->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, "", "");
1396 }
1397 
InitImageErrorCallback(const RefPtr<SideBarTheme> & sideBarTheme,const RefPtr<FrameNode> & imgNode)1398 void SideBarContainerPattern::InitImageErrorCallback(const RefPtr<SideBarTheme>& sideBarTheme,
1399     const RefPtr<FrameNode>& imgNode)
1400 {
1401     auto eventHub = imgNode->GetEventHub<ImageEventHub>();
1402     CHECK_NULL_VOID(eventHub);
1403     auto errorCallback = [weakPattern = WeakClaim(this), weakNode = WeakClaim(RawPtr(imgNode)),
1404         weakTheme = WeakClaim(RawPtr(sideBarTheme))] (const LoadImageFailEvent& info) {
1405         auto imgNode = weakNode.Upgrade();
1406         CHECK_NULL_VOID(imgNode);
1407         auto imageLayoutProperty = imgNode->GetLayoutProperty<ImageLayoutProperty>();
1408         CHECK_NULL_VOID(imageLayoutProperty);
1409         auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo();
1410         if (!imageSourceInfo.has_value()) {
1411             return;
1412         }
1413         auto infoValue = imageSourceInfo.value();
1414         infoValue.SetResourceId(InternalResource::ResourceId::SIDE_BAR);
1415         auto sideBarTheme = weakTheme.Upgrade();
1416         CHECK_NULL_VOID(sideBarTheme);
1417         auto controlButtonColor = sideBarTheme->GetControlImageColor();
1418         infoValue.SetFillColor(controlButtonColor);
1419         imageLayoutProperty->UpdateImageSourceInfo(infoValue);
1420         auto pattern = weakPattern.Upgrade();
1421         CHECK_NULL_VOID(pattern);
1422         pattern->SetImageInfo(infoValue);
1423         imgNode->MarkModifyDone();
1424     };
1425     eventHub->SetOnError(errorCallback);
1426 }
1427 } // namespace OHOS::Ace::NG
1428