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