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