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/tabs/tabs_model_ng.h"
17 
18 #include <type_traits>
19 
20 #include "base/log/ace_trace.h"
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/utils/utils.h"
24 #include "core/animation/animation_pub.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/common/properties/decoration.h"
27 #include "core/components/swiper/swiper_controller.h"
28 #include "core/components_ng/base/group_node.h"
29 #include "core/components_ng/base/view_stack_processor.h"
30 #include "core/components_ng/pattern/divider/divider_layout_property.h"
31 #include "core/components_ng/pattern/divider/divider_pattern.h"
32 #include "core/components_ng/pattern/divider/divider_render_property.h"
33 #include "core/components_ng/pattern/image/image_pattern.h"
34 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
35 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
36 #include "core/components_ng/pattern/swiper/swiper_paint_property.h"
37 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
38 #include "core/components_ng/pattern/tabs/tab_bar_paint_property.h"
39 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
40 #include "core/components_ng/pattern/tabs/tabs_controller.h"
41 #include "core/components_ng/pattern/tabs/tabs_node.h"
42 #include "core/components_ng/pattern/tabs/tabs_pattern.h"
43 #include "core/components_ng/pattern/text/text_pattern.h"
44 #include "core/components_ng/property/measure_utils.h"
45 #include "core/components_ng/property/safe_area_insets.h"
46 #include "core/components_v2/inspector/inspector_constants.h"
47 
48 namespace OHOS::Ace::NG {
49 namespace {
50 constexpr uint16_t PIXEL_ROUND = static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_START) |
51                                 static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_TOP) |
52                                 static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_END) |
53                                 static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM);
54 constexpr char APP_TABS_NO_ANIMATION_SWITCH[] = "APP_TABS_NO_ANIMATION_SWITCH";
55 } // namespace
56 
Create(BarPosition barPosition,int32_t index,const RefPtr<TabController> &,const RefPtr<SwiperController> & swiperController)57 void TabsModelNG::Create(BarPosition barPosition, int32_t index, const RefPtr<TabController>& /*tabController*/,
58     const RefPtr<SwiperController>& swiperController)
59 {
60     auto* stack = ViewStackProcessor::GetInstance();
61     auto nodeId = stack->ClaimNodeId();
62     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::TABS_ETS_TAG, nodeId);
63     auto tabsNode = GetOrCreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<TabsPattern>(); });
64     auto hasTabBarNode = tabsNode->HasTabBarNode();
65     InitTabsNode(tabsNode, swiperController);
66     ViewStackProcessor::GetInstance()->Push(tabsNode);
67 
68     SetTabBarPosition(barPosition);
69     if (!hasTabBarNode) {
70         auto tabsFrameNode = AceType::DynamicCast<FrameNode>(tabsNode);
71         CHECK_NULL_VOID(tabsFrameNode);
72         auto tabsLayoutProperty = tabsFrameNode->GetLayoutProperty<TabsLayoutProperty>();
73         tabsLayoutProperty->UpdateIndex(index < 0 ? 0 : index);
74         return;
75     }
76     auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
77     auto preIndex = tabsLayoutProperty->GetIndexValue(0);
78     auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
79     CHECK_NULL_VOID(tabsPattern);
80     if (tabsPattern->GetInterceptStatus() && preIndex != index) {
81         auto ret = tabsPattern->OnContentWillChange(preIndex, index);
82         if (ret.has_value() && !ret.value()) {
83             return;
84         }
85     }
86     if ((index != preIndex) && (index >= 0)) {
87         AceAsyncTraceBeginCommercial(0, APP_TABS_NO_ANIMATION_SWITCH);
88         SetIndex(index);
89         auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
90         auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
91         tabBarPattern->SetMaskAnimationByCreate(true);
92         tabBarPattern->UpdateImageColor(index);
93         tabBarPattern->UpdateSymbolStats(index, -1);
94         tabBarPattern->UpdateSymbolStats(-1, preIndex);
95     }
96 }
97 
GetSwiperController(const RefPtr<FrameNode> & swiperNode,const RefPtr<SwiperController> & swiperController)98 RefPtr<SwiperController> TabsModelNG::GetSwiperController(const RefPtr<FrameNode>& swiperNode,
99     const RefPtr<SwiperController>& swiperController)
100 {
101     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
102     swiperPaintProperty->UpdateEdgeEffect(EdgeEffect::SPRING);
103     auto pipelineContext = PipelineContext::GetCurrentContext();
104     CHECK_NULL_RETURN(pipelineContext, nullptr);
105     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
106     CHECK_NULL_RETURN(tabTheme, nullptr);
107     swiperPaintProperty->UpdateDuration(tabTheme->GetTabContentAnimationDuration());
108     swiperPaintProperty->UpdateCurve(TabBarPhysicalCurve);
109     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
110     swiperLayoutProperty->UpdateLoop(false);
111     swiperLayoutProperty->UpdateCachedCount(0);
112     swiperLayoutProperty->UpdateShowIndicator(false);
113     swiperLayoutProperty->UpdateSafeAreaExpandOpts(
114         { .type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_TOP + SAFE_AREA_EDGE_BOTTOM });
115     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
116     CHECK_NULL_RETURN(swiperPattern, nullptr);
117     RefPtr<SwiperController> controller;
118     if (swiperController) {
119         controller = swiperController;
120     } else {
121         controller = AceType::MakeRefPtr<TabsControllerNG>();
122     }
123     swiperPattern->SetSwiperController(controller);
124     swiperPattern->SetFinishCallbackType(FinishCallbackType::LOGICALLY);
125     swiperPattern->SetHasTabsAncestor(true);
126     return controller;
127 }
128 
InitSelectedMaskNode(const RefPtr<FrameNode> & selectedMaskNode)129 void TabsModelNG::InitSelectedMaskNode(const RefPtr<FrameNode>& selectedMaskNode)
130 {
131     auto selectedImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
132         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
133     selectedImageNode->MountToParent(selectedMaskNode);
134     auto selectedMaskRenderContext = selectedMaskNode->GetRenderContext();
135     auto selectedMaskProperty = selectedMaskNode->GetLayoutProperty<LinearLayoutProperty>();
136     selectedMaskProperty->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
137     selectedMaskRenderContext->SetClipToBounds(true);
138 }
139 
InitUnselectedMaskNode(const RefPtr<FrameNode> & unselectedMaskNode)140 void TabsModelNG::InitUnselectedMaskNode(const RefPtr<FrameNode>& unselectedMaskNode)
141 {
142     auto unselectedImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
143         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
144     unselectedImageNode->MountToParent(unselectedMaskNode);
145     auto unselectedMaskRenderContext = unselectedMaskNode->GetRenderContext();
146     auto unselectedMaskProperty = unselectedMaskNode->GetLayoutProperty<LinearLayoutProperty>();
147     unselectedMaskProperty->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
148     unselectedMaskRenderContext->SetClipToBounds(true);
149 }
150 
InitTabsNode(RefPtr<TabsNode> tabsNode,const RefPtr<SwiperController> & swiperController)151 void TabsModelNG::InitTabsNode(RefPtr<TabsNode> tabsNode, const RefPtr<SwiperController>& swiperController)
152 {
153     bool hasSwiperNode = tabsNode->HasSwiperNode();
154     bool hasTabBarNode = tabsNode->HasTabBarNode();
155     bool hasDividerNode = tabsNode->HasDividerNode();
156     bool hasSelectedMaskNode = tabsNode->HasSelectedMaskNode();
157     bool hasUnselectedMaskNode = tabsNode->HasUnselectedMaskNode();
158     auto swiperId = tabsNode->GetSwiperId();
159     auto tabBarId = tabsNode->GetTabBarId();
160     auto dividerId = tabsNode->GetDividerId();
161     auto selectedMaskId = tabsNode->GetSelectedMaskId();
162     auto unselectedMaskId = tabsNode->GetUnselectedMaskId();
163 
164     // Create Swiper node to contain TabContent.
165     auto swiperNode = FrameNode::GetOrCreateFrameNode(
166         V2::SWIPER_ETS_TAG, swiperId, []() { return AceType::MakeRefPtr<SwiperPattern>(); });
167     auto controller = GetSwiperController(swiperNode, swiperController);
168     auto dividerNode = FrameNode::GetOrCreateFrameNode(
169         V2::DIVIDER_ETS_TAG, dividerId, []() { return AceType::MakeRefPtr<DividerPattern>(); });
170 
171     // Create TabBar to contain TabBar of TabContent.
172     auto tabBarNode = FrameNode::GetOrCreateFrameNode(
173         V2::TAB_BAR_ETS_TAG, tabBarId, [controller]() { return AceType::MakeRefPtr<TabBarPattern>(controller); });
174 
175     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty();
176     CHECK_NULL_VOID(tabBarLayoutProperty);
177     tabBarLayoutProperty->UpdatePixelRound(PIXEL_ROUND);
178 
179     auto selectedMaskNode = FrameNode::GetOrCreateFrameNode(
180         V2::COLUMN_ETS_TAG, selectedMaskId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
181 
182     auto unselectedMaskNode = FrameNode::GetOrCreateFrameNode(
183         V2::COLUMN_ETS_TAG, unselectedMaskId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
184 
185     if (!hasSwiperNode) {
186         swiperNode->MountToParent(tabsNode);
187     }
188     if (!hasDividerNode) {
189         dividerNode->MountToParent(tabsNode);
190     }
191     if (!hasTabBarNode) {
192         tabBarNode->MountToParent(tabsNode);
193     }
194     if (!hasSelectedMaskNode) {
195         selectedMaskNode->MountToParent(tabBarNode);
196         InitSelectedMaskNode(selectedMaskNode);
197     }
198     if (!hasUnselectedMaskNode) {
199         unselectedMaskNode->MountToParent(tabBarNode);
200         InitUnselectedMaskNode(unselectedMaskNode);
201     }
202 }
203 
CreateFrameNode(int32_t nodeId)204 RefPtr<FrameNode> TabsModelNG::CreateFrameNode(int32_t nodeId)
205 {
206     auto tabsNode = GetOrCreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<TabsPattern>(); });
207     InitTabsNode(tabsNode, nullptr);
208     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
209     tabBarNode->MarkModifyDone();
210     return tabsNode;
211 }
212 
SetTabBarPosition(BarPosition tabBarPosition)213 void TabsModelNG::SetTabBarPosition(BarPosition tabBarPosition)
214 {
215     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarPosition, tabBarPosition);
216 }
217 
SetBarBackgroundBlurStyle(BlurStyle tabBarBlurStyle)218 void TabsModelNG::SetBarBackgroundBlurStyle(BlurStyle tabBarBlurStyle)
219 {
220     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
221     CHECK_NULL_VOID(tabsNode);
222     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
223     CHECK_NULL_VOID(tabBarNode);
224     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
225     CHECK_NULL_VOID(tabBarPaintProperty);
226     tabBarPaintProperty->UpdateTabBarBlurStyle(tabBarBlurStyle);
227 }
228 
SetTabBarMode(TabBarMode tabBarMode)229 void TabsModelNG::SetTabBarMode(TabBarMode tabBarMode)
230 {
231     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarMode, tabBarMode);
232     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
233     CHECK_NULL_VOID(tabBarLayoutProperty);
234     tabBarLayoutProperty->UpdateTabBarMode(tabBarMode);
235 }
236 
SetTabBarWidth(const Dimension & tabBarWidth)237 void TabsModelNG::SetTabBarWidth(const Dimension& tabBarWidth)
238 {
239     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarWidth, tabBarWidth);
240     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
241     CHECK_NULL_VOID(tabsNode);
242     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
243     CHECK_NULL_VOID(tabBarNode);
244     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
245     CHECK_NULL_VOID(tabBarLayoutProperty);
246     auto scaleProperty = ScaleProperty::CreateScaleProperty();
247     auto tabBarWidthToPx =
248         ConvertToPx(tabBarWidth, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Width());
249     if (LessNotEqual(tabBarWidthToPx.value_or(0.0), 0.0)) {
250         tabBarLayoutProperty->ClearUserDefinedIdealSize(true, false);
251     } else {
252         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(tabBarWidth), std::nullopt));
253     }
254     tabBarLayoutProperty->UpdateTabBarWidth(tabBarWidth);
255 }
256 
SetTabBarHeight(const Dimension & tabBarHeight)257 void TabsModelNG::SetTabBarHeight(const Dimension& tabBarHeight)
258 {
259     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarHeight, tabBarHeight);
260     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
261     CHECK_NULL_VOID(tabsNode);
262     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
263     CHECK_NULL_VOID(tabBarNode);
264     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
265     CHECK_NULL_VOID(tabBarLayoutProperty);
266     auto scaleProperty = ScaleProperty::CreateScaleProperty();
267     auto tabBarHeightToPx = ConvertToPx(
268         tabBarHeight, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Height());
269     if (LessNotEqual(tabBarHeightToPx.value_or(0.0), 0.0)) {
270         tabBarLayoutProperty->ClearUserDefinedIdealSize(false, true);
271     } else {
272         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, NG::CalcLength(tabBarHeight)));
273     }
274     tabBarLayoutProperty->UpdateTabBarHeight(tabBarHeight);
275 }
276 
SetWidthAuto(bool isAuto)277 void TabsModelNG::SetWidthAuto(bool isAuto)
278 {
279     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
280     CHECK_NULL_VOID(frameNode);
281     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, WidthAuto, isAuto);
282 }
283 
SetWidthAuto(FrameNode * frameNode,bool isAuto)284 void TabsModelNG::SetWidthAuto(FrameNode* frameNode, bool isAuto)
285 {
286     CHECK_NULL_VOID(frameNode);
287     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, WidthAuto, isAuto, frameNode);
288 }
289 
SetHeightAuto(bool isAuto)290 void TabsModelNG::SetHeightAuto(bool isAuto)
291 {
292     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
293     CHECK_NULL_VOID(frameNode);
294     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, HeightAuto, isAuto);
295 }
296 
SetHeightAuto(FrameNode * frameNode,bool isAuto)297 void TabsModelNG::SetHeightAuto(FrameNode* frameNode, bool isAuto)
298 {
299     CHECK_NULL_VOID(frameNode);
300     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, HeightAuto, isAuto, frameNode);
301 }
302 
SetBarAdaptiveHeight(bool barAdaptiveHeight)303 void TabsModelNG::SetBarAdaptiveHeight(bool barAdaptiveHeight)
304 {
305     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
306     CHECK_NULL_VOID(tabBarLayoutProperty);
307     tabBarLayoutProperty->UpdateBarAdaptiveHeight(barAdaptiveHeight);
308 }
309 
SetIsVertical(bool isVertical)310 void TabsModelNG::SetIsVertical(bool isVertical)
311 {
312     auto axis = isVertical ? Axis::VERTICAL : Axis::HORIZONTAL;
313     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Axis, axis);
314 
315     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
316     CHECK_NULL_VOID(tabBarLayoutProperty);
317     if (tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL) != axis) {
318         auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
319         CHECK_NULL_VOID(tabsNode);
320         auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
321         CHECK_NULL_VOID(tabBarNode);
322         auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
323         CHECK_NULL_VOID(tabBarPattern);
324         tabBarPattern->UpdateCurrentOffset(0.0f);
325     }
326     tabBarLayoutProperty->UpdateAxis(axis);
327     auto swiperLayoutProperty = GetSwiperLayoutProperty();
328     CHECK_NULL_VOID(swiperLayoutProperty);
329     swiperLayoutProperty->UpdateDirection(axis);
330 }
331 
SetIndex(int32_t index)332 void TabsModelNG::SetIndex(int32_t index)
333 {
334     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
335     CHECK_NULL_VOID(tabsNode);
336     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
337     CHECK_NULL_VOID(swiperNode);
338     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
339     CHECK_NULL_VOID(swiperLayoutProperty);
340     swiperLayoutProperty->UpdateIndex(index);
341     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
342     CHECK_NULL_VOID(tabBarNode);
343     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
344     CHECK_NULL_VOID(tabBarPattern);
345     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
346     CHECK_NULL_VOID(tabBarLayoutProperty);
347     if (index < 0) {
348         index = 0;
349     }
350     tabBarLayoutProperty->UpdateIndicator(index);
351     tabBarPattern->SetClickRepeat(false);
352     tabBarPattern->UpdateTextColorAndFontWeight(index);
353     swiperLayoutProperty->UpdateIndex(index);
354     auto tabsFrameNode = AceType::DynamicCast<FrameNode>(tabsNode);
355     CHECK_NULL_VOID(tabsFrameNode);
356     auto tabsLayoutProperty = tabsFrameNode->GetLayoutProperty<TabsLayoutProperty>();
357     tabsLayoutProperty->UpdateIndex(index);
358     swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
359 }
360 
SetScrollable(bool scrollable)361 void TabsModelNG::SetScrollable(bool scrollable)
362 {
363     auto props = GetSwiperLayoutProperty();
364     CHECK_NULL_VOID(props);
365     props->UpdateDisableSwipe(!scrollable);
366     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
367     CHECK_NULL_VOID(tabsNode);
368     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
369     CHECK_NULL_VOID(tabPattern);
370     tabPattern->SetIsDisableSwipe(!scrollable);
371 }
372 
SetAnimationDuration(float duration)373 void TabsModelNG::SetAnimationDuration(float duration)
374 {
375     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
376     CHECK_NULL_VOID(tabsNode);
377     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
378     CHECK_NULL_VOID(tabBarNode);
379     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
380     CHECK_NULL_VOID(tabBarPattern);
381     tabBarPattern->SetAnimationDuration(static_cast<int32_t>(duration));
382     if (static_cast<int32_t>(duration) < 0) {
383         return;
384     }
385     auto swiperPaintProperty = GetSwiperPaintProperty();
386     CHECK_NULL_VOID(swiperPaintProperty);
387     swiperPaintProperty->UpdateDuration(static_cast<int32_t>(duration));
388 }
389 
SetFadingEdge(bool fadingEdge)390 void TabsModelNG::SetFadingEdge(bool fadingEdge)
391 {
392     auto tabBarPaintProperty = GetTabBarPaintProperty();
393     CHECK_NULL_VOID(tabBarPaintProperty);
394     tabBarPaintProperty->UpdateFadingEdge(fadingEdge);
395 }
396 
SetBarOverlap(bool barOverlap)397 void TabsModelNG::SetBarOverlap(bool barOverlap)
398 {
399     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarOverlap, barOverlap);
400 
401     if (barOverlap) {
402         SetBarBackgroundBlurStyle(BlurStyle::COMPONENT_THICK);
403     } else {
404         SetBarBackgroundBlurStyle(BlurStyle::NO_MATERIAL);
405     }
406 }
407 
SetOnChange(std::function<void (const BaseEventInfo *)> && onChange)408 void TabsModelNG::SetOnChange(std::function<void(const BaseEventInfo*)>&& onChange)
409 {
410     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
411     CHECK_NULL_VOID(tabsNode);
412     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
413     CHECK_NULL_VOID(tabPattern);
414     tabPattern->SetOnChangeEvent(std::move(onChange));
415 }
416 
SetOnTabBarClick(std::function<void (const BaseEventInfo *)> && onTabBarClick)417 void TabsModelNG::SetOnTabBarClick(std::function<void(const BaseEventInfo*)>&& onTabBarClick)
418 {
419     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
420     CHECK_NULL_VOID(tabsNode);
421     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
422     CHECK_NULL_VOID(tabPattern);
423     tabPattern->SetOnTabBarClickEvent(std::move(onTabBarClick));
424 }
425 
SetOnAnimationStart(AnimationStartEvent && onAnimationStart)426 void TabsModelNG::SetOnAnimationStart(AnimationStartEvent&& onAnimationStart)
427 {
428     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
429     CHECK_NULL_VOID(tabsNode);
430     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
431     CHECK_NULL_VOID(tabPattern);
432     tabPattern->SetAnimationStartEvent(std::move(onAnimationStart));
433 }
434 
SetOnAnimationEnd(AnimationEndEvent && onAnimationEnd)435 void TabsModelNG::SetOnAnimationEnd(AnimationEndEvent&& onAnimationEnd)
436 {
437     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
438     CHECK_NULL_VOID(tabsNode);
439     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
440     CHECK_NULL_VOID(tabPattern);
441     tabPattern->SetAnimationEndEvent(std::move(onAnimationEnd));
442 }
443 
SetOnGestureSwipe(GestureSwipeEvent && onGestureSwipe)444 void TabsModelNG::SetOnGestureSwipe(GestureSwipeEvent&& onGestureSwipe)
445 {
446     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
447     CHECK_NULL_VOID(tabsNode);
448     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
449     CHECK_NULL_VOID(swiperNode);
450     auto eventHub = swiperNode->GetEventHub<SwiperEventHub>();
451     CHECK_NULL_VOID(eventHub);
452     eventHub->SetGestureSwipeEvent(std::move(onGestureSwipe));
453 }
454 
SetDivider(const TabsItemDivider & divider)455 void TabsModelNG::SetDivider(const TabsItemDivider& divider)
456 {
457     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
458     CHECK_NULL_VOID(tabsNode);
459     auto dividerNode = AceType::DynamicCast<FrameNode>(tabsNode->GetChildAtIndex(1));
460     CHECK_NULL_VOID(dividerNode);
461     auto dividerRenderContext = dividerNode->GetRenderContext();
462     CHECK_NULL_VOID(dividerRenderContext);
463     if (divider.isNull) {
464         dividerRenderContext->UpdateOpacity(0.0f);
465         auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
466         CHECK_NULL_VOID(tabsLayoutProperty);
467         auto currentDivider = tabsLayoutProperty->GetDivider().value_or(TabsItemDivider());
468         currentDivider.strokeWidth = Dimension(1.0f);
469         currentDivider.isNull = true;
470         ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, currentDivider);
471     } else {
472         dividerRenderContext->UpdateOpacity(1.0f);
473         ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, divider);
474     }
475 }
476 
SetBarBackgroundColor(const Color & backgroundColor)477 void TabsModelNG::SetBarBackgroundColor(const Color& backgroundColor)
478 {
479     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
480     CHECK_NULL_VOID(tabsNode);
481     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
482     CHECK_NULL_VOID(tabBarNode);
483     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
484     CHECK_NULL_VOID(tabBarPaintProperty);
485     tabBarPaintProperty->UpdateBarBackgroundColor(backgroundColor);
486     auto tabBarRenderContext = tabBarNode->GetRenderContext();
487     CHECK_NULL_VOID(tabBarRenderContext);
488     tabBarRenderContext->UpdateBackgroundColor(backgroundColor);
489 }
490 
GetTabBarLayoutProperty()491 RefPtr<TabBarLayoutProperty> TabsModelNG::GetTabBarLayoutProperty()
492 {
493     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
494     CHECK_NULL_RETURN(tabsNode, nullptr);
495     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
496     CHECK_NULL_RETURN(tabBarNode, nullptr);
497     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
498     CHECK_NULL_RETURN(tabBarLayoutProperty, nullptr);
499     return tabBarLayoutProperty;
500 }
501 
GetTabBarPaintProperty()502 RefPtr<TabBarPaintProperty> TabsModelNG::GetTabBarPaintProperty()
503 {
504     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
505     CHECK_NULL_RETURN(tabsNode, nullptr);
506     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
507     CHECK_NULL_RETURN(tabBarNode, nullptr);
508     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
509     CHECK_NULL_RETURN(tabBarPaintProperty, nullptr);
510     return tabBarPaintProperty;
511 }
512 
GetSwiperLayoutProperty()513 RefPtr<SwiperLayoutProperty> TabsModelNG::GetSwiperLayoutProperty()
514 {
515     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
516     CHECK_NULL_RETURN(tabsNode, nullptr);
517     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
518     CHECK_NULL_RETURN(swiperNode, nullptr);
519     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
520     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
521     return swiperLayoutProperty;
522 }
523 
GetSwiperPaintProperty()524 RefPtr<SwiperPaintProperty> TabsModelNG::GetSwiperPaintProperty()
525 {
526     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
527     CHECK_NULL_RETURN(tabsNode, nullptr);
528     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
529     CHECK_NULL_RETURN(swiperNode, nullptr);
530     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
531     CHECK_NULL_RETURN(swiperPaintProperty, nullptr);
532     return swiperPaintProperty;
533 }
534 
Pop()535 void TabsModelNG::Pop()
536 {
537     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
538     CHECK_NULL_VOID(tabsNode);
539     auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
540     auto index = tabsLayoutProperty->GetIndexValue(0);
541     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
542     CHECK_NULL_VOID(tabBarNode);
543     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
544     CHECK_NULL_VOID(tabBarPattern);
545     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
546     CHECK_NULL_VOID(tabBarLayoutProperty);
547     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
548     CHECK_NULL_VOID(swiperNode);
549     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
550     CHECK_NULL_VOID(swiperLayoutProperty);
551 
552     auto tabBarPosition = tabsLayoutProperty->GetTabBarPosition().value_or(BarPosition::START);
553     auto tabsFocusNode = tabsNode->GetFocusHub();
554     CHECK_NULL_VOID(tabsFocusNode);
555     auto tabBarFocusNode = tabBarNode->GetFocusHub();
556     CHECK_NULL_VOID(tabBarFocusNode);
557     if (tabBarPosition == BarPosition::START && !tabsFocusNode->IsCurrentFocus()) {
558         auto lastWeakFocusNode = tabsFocusNode->GetLastWeakFocusNode().Upgrade();
559         if (!lastWeakFocusNode) {
560             tabsFocusNode->SetLastWeakFocusNode(AceType::WeakClaim(AceType::RawPtr(tabBarFocusNode)));
561         }
562     }
563 
564     auto tabContentNum = swiperNode->TotalChildCount();
565     if (index > tabContentNum - 1 || index < 0) {
566         index = 0;
567     }
568     tabBarLayoutProperty->UpdateIndicator(index);
569     tabBarPattern->SetClickRepeat(false);
570     tabBarPattern->UpdateTextColorAndFontWeight(index);
571     swiperLayoutProperty->UpdateIndex(index);
572 
573     tabBarNode->MarkModifyDone();
574     tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
575     auto dividerNode = AceType::DynamicCast<FrameNode>(tabsNode->GetDivider());
576     CHECK_NULL_VOID(dividerNode);
577     auto layoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
578     CHECK_NULL_VOID(layoutProperty);
579 
580     auto axis = layoutProperty->GetAxis().value_or((Axis::HORIZONTAL));
581     TabsItemDivider defaultDivider;
582     auto divider = layoutProperty->GetDivider().value_or(defaultDivider);
583     auto dividerColor = divider.color;
584     auto dividerStrokeWidth = divider.strokeWidth;
585 
586     auto dividerHub = dividerNode->GetEventHub<EventHub>();
587     CHECK_NULL_VOID(dividerHub);
588 
589     auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
590     CHECK_NULL_VOID(dividerRenderProperty);
591     dividerRenderProperty->UpdateDividerColor(dividerColor);
592     dividerRenderProperty->UpdateLineCap(LineCap::BUTT);
593 
594     auto dividerLayoutProperty = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
595     CHECK_NULL_VOID(dividerLayoutProperty);
596     dividerLayoutProperty->UpdateVertical(axis == Axis::VERTICAL);
597     dividerLayoutProperty->UpdateStrokeWidth(dividerStrokeWidth);
598     dividerLayoutProperty->UpdateStrokeWidthLimitation(false);
599     CHECK_NULL_VOID(dividerNode);
600     dividerNode->MarkModifyDone();
601 
602     swiperNode->MarkModifyDone();
603     swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
604 
605     ViewStackProcessor::GetInstance()->PopContainer();
606 }
607 
GetOrCreateTabsNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)608 RefPtr<TabsNode> TabsModelNG::GetOrCreateTabsNode(
609     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
610 {
611     auto tabsNode = ElementRegister::GetInstance()->GetSpecificItemById<TabsNode>(nodeId);
612     if (tabsNode) {
613         if (tabsNode->GetTag() == tag) {
614             return tabsNode;
615         }
616         ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
617         auto parent = tabsNode->GetParent();
618         if (parent) {
619             parent->RemoveChild(tabsNode);
620         }
621     }
622 
623     auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
624     tabsNode = AceType::MakeRefPtr<TabsNode>(tag, nodeId, pattern, false);
625     tabsNode->InitializePatternAndContext();
626     ElementRegister::GetInstance()->AddUINode(tabsNode);
627     return tabsNode;
628 }
629 
SetOnChangeEvent(std::function<void (const BaseEventInfo *)> && onChangeEvent)630 void TabsModelNG::SetOnChangeEvent(std::function<void(const BaseEventInfo*)>&& onChangeEvent)
631 {
632     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
633     CHECK_NULL_VOID(tabsNode);
634     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
635     CHECK_NULL_VOID(tabPattern);
636     tabPattern->SetOnIndexChangeEvent(std::move(onChangeEvent));
637 }
638 
SetClipEdge(bool clipEdge)639 void TabsModelNG::SetClipEdge(bool clipEdge)
640 {
641     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
642     CHECK_NULL_VOID(tabsNode);
643     ViewAbstract::SetClipEdge(clipEdge);
644     auto tabsChildren = tabsNode->GetChildren();
645     for (const auto& child : tabsChildren) {
646         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
647         CHECK_NULL_VOID(childFrameNode);
648         auto renderContext = childFrameNode->GetRenderContext();
649         CHECK_NULL_VOID(renderContext);
650         renderContext->UpdateClipEdge(clipEdge);
651     }
652 }
653 
SetScrollableBarModeOptions(const ScrollableBarModeOptions & option)654 void TabsModelNG::SetScrollableBarModeOptions(const ScrollableBarModeOptions& option)
655 {
656     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
657     CHECK_NULL_VOID(tabBarLayoutProperty);
658     tabBarLayoutProperty->UpdateScrollableBarModeOptions(option);
659 }
660 
SetBarGridAlign(const BarGridColumnOptions & BarGridColumnOptions)661 void TabsModelNG::SetBarGridAlign(const BarGridColumnOptions& BarGridColumnOptions)
662 {
663     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
664     CHECK_NULL_VOID(tabBarLayoutProperty);
665     tabBarLayoutProperty->UpdateBarGridAlign(BarGridColumnOptions);
666 }
667 
GetTabBarLayoutProperty(FrameNode * frameNode)668 RefPtr<TabBarLayoutProperty> TabsModelNG::GetTabBarLayoutProperty(FrameNode* frameNode)
669 {
670     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
671     CHECK_NULL_RETURN(tabsNode, nullptr);
672     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
673     CHECK_NULL_RETURN(tabBarNode, nullptr);
674     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
675     CHECK_NULL_RETURN(tabBarLayoutProperty, nullptr);
676     return tabBarLayoutProperty;
677 }
678 
GetTabBarPaintProperty(FrameNode * frameNode)679 RefPtr<TabBarPaintProperty> TabsModelNG::GetTabBarPaintProperty(FrameNode* frameNode)
680 {
681     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
682     CHECK_NULL_RETURN(tabsNode, nullptr);
683     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
684     CHECK_NULL_RETURN(tabBarNode, nullptr);
685     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
686     CHECK_NULL_RETURN(tabBarPaintProperty, nullptr);
687     return tabBarPaintProperty;
688 }
689 
GetSwiperLayoutProperty(FrameNode * frameNode)690 RefPtr<SwiperLayoutProperty> TabsModelNG::GetSwiperLayoutProperty(FrameNode* frameNode)
691 {
692     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
693     CHECK_NULL_RETURN(tabsNode, nullptr);
694     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
695     CHECK_NULL_RETURN(swiperNode, nullptr);
696     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
697     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
698     return swiperLayoutProperty;
699 }
700 
GetSwiperPaintProperty(FrameNode * frameNode)701 RefPtr<SwiperPaintProperty> TabsModelNG::GetSwiperPaintProperty(FrameNode* frameNode)
702 {
703     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
704     CHECK_NULL_RETURN(tabsNode, nullptr);
705     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
706     CHECK_NULL_RETURN(swiperNode, nullptr);
707     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
708     CHECK_NULL_RETURN(swiperPaintProperty, nullptr);
709     return swiperPaintProperty;
710 }
711 
SetTabBarMode(FrameNode * frameNode,TabBarMode tabBarMode)712 void TabsModelNG::SetTabBarMode(FrameNode* frameNode, TabBarMode tabBarMode)
713 {
714     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarMode, tabBarMode, frameNode);
715     auto tabBarLayoutProperty = GetTabBarLayoutProperty(frameNode);
716     CHECK_NULL_VOID(tabBarLayoutProperty);
717     tabBarLayoutProperty->UpdateTabBarMode(tabBarMode);
718 }
719 
SetBarGridAlign(FrameNode * frameNode,const BarGridColumnOptions & BarGridColumnOptions)720 void TabsModelNG::SetBarGridAlign(FrameNode* frameNode, const BarGridColumnOptions& BarGridColumnOptions)
721 {
722     CHECK_NULL_VOID(frameNode);
723     auto tabBarLayoutProperty = GetTabBarLayoutProperty(frameNode);
724     CHECK_NULL_VOID(tabBarLayoutProperty);
725     tabBarLayoutProperty->UpdateBarGridAlign(BarGridColumnOptions);
726 }
727 
SetDivider(FrameNode * frameNode,const TabsItemDivider & divider)728 void TabsModelNG::SetDivider(FrameNode* frameNode, const TabsItemDivider& divider)
729 {
730     CHECK_NULL_VOID(frameNode);
731     auto dividerNode = AceType::DynamicCast<FrameNode>(frameNode->GetChildAtIndex(1));
732     CHECK_NULL_VOID(dividerNode);
733     auto dividerRenderContext = dividerNode->GetRenderContext();
734     CHECK_NULL_VOID(dividerRenderContext);
735     if (divider.isNull) {
736         dividerRenderContext->UpdateOpacity(0.0f);
737         auto tabsLayoutProperty = frameNode->GetLayoutProperty<TabsLayoutProperty>();
738         CHECK_NULL_VOID(tabsLayoutProperty);
739         auto currentDivider = tabsLayoutProperty->GetDivider().value_or(TabsItemDivider());
740         currentDivider.strokeWidth = Dimension(1.0f);
741         currentDivider.isNull = true;
742         ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, currentDivider, frameNode);
743     } else {
744         dividerRenderContext->UpdateOpacity(1.0f);
745         ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, divider, frameNode);
746     }
747 }
748 
SetFadingEdge(FrameNode * frameNode,bool fadingEdge)749 void TabsModelNG::SetFadingEdge(FrameNode* frameNode, bool fadingEdge)
750 {
751     CHECK_NULL_VOID(frameNode);
752     auto tabBarPaintProperty = GetTabBarPaintProperty(frameNode);
753     CHECK_NULL_VOID(tabBarPaintProperty);
754     tabBarPaintProperty->UpdateFadingEdge(fadingEdge);
755 }
756 
SetBarBackgroundColor(FrameNode * frameNode,const Color & backgroundColor)757 void TabsModelNG::SetBarBackgroundColor(FrameNode* frameNode, const Color& backgroundColor)
758 {
759     CHECK_NULL_VOID(frameNode);
760     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
761     CHECK_NULL_VOID(tabsNode);
762     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
763     CHECK_NULL_VOID(tabBarNode);
764     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
765     CHECK_NULL_VOID(tabBarPaintProperty);
766     tabBarPaintProperty->UpdateBarBackgroundColor(backgroundColor);
767     auto tabBarRenderContext = tabBarNode->GetRenderContext();
768     CHECK_NULL_VOID(tabBarRenderContext);
769     tabBarRenderContext->UpdateBackgroundColor(backgroundColor);
770 }
771 
SetBarBackgroundBlurStyle(FrameNode * frameNode,BlurStyle tabBarBlurStyle)772 void TabsModelNG::SetBarBackgroundBlurStyle(FrameNode* frameNode, BlurStyle tabBarBlurStyle)
773 {
774     CHECK_NULL_VOID(frameNode);
775     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
776     CHECK_NULL_VOID(tabsNode);
777     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
778     CHECK_NULL_VOID(tabBarNode);
779     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
780     CHECK_NULL_VOID(tabBarPaintProperty);
781     tabBarPaintProperty->UpdateTabBarBlurStyle(tabBarBlurStyle);
782 }
783 
SetBarOverlap(FrameNode * frameNode,bool barOverlap)784 void TabsModelNG::SetBarOverlap(FrameNode* frameNode, bool barOverlap)
785 {
786     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, BarOverlap, barOverlap, frameNode);
787 
788     if (barOverlap) {
789         SetBarBackgroundBlurStyle(frameNode, BlurStyle::COMPONENT_THICK);
790     } else {
791         SetBarBackgroundBlurStyle(frameNode, BlurStyle::NO_MATERIAL);
792     }
793 }
794 
SetIsVertical(FrameNode * frameNode,bool isVertical)795 void TabsModelNG::SetIsVertical(FrameNode* frameNode, bool isVertical)
796 {
797     auto axis = isVertical ? Axis::VERTICAL : Axis::HORIZONTAL;
798     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, Axis, axis, frameNode);
799 
800     auto tabBarLayoutProperty = GetTabBarLayoutProperty(frameNode);
801     CHECK_NULL_VOID(tabBarLayoutProperty);
802     if (tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL) != axis) {
803         auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
804         CHECK_NULL_VOID(tabsNode);
805         auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
806         CHECK_NULL_VOID(tabBarNode);
807         auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
808         CHECK_NULL_VOID(tabBarPattern);
809         tabBarPattern->UpdateCurrentOffset(0.0f);
810     }
811     tabBarLayoutProperty->UpdateAxis(axis);
812     auto swiperLayoutProperty = GetSwiperLayoutProperty(frameNode);
813     CHECK_NULL_VOID(swiperLayoutProperty);
814     swiperLayoutProperty->UpdateDirection(axis);
815 }
816 
SetTabBarPosition(FrameNode * frameNode,BarPosition tabBarPosition)817 void TabsModelNG::SetTabBarPosition(FrameNode* frameNode, BarPosition tabBarPosition)
818 {
819     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarPosition, tabBarPosition, frameNode);
820 }
821 
SetScrollable(FrameNode * frameNode,bool scrollable)822 void TabsModelNG::SetScrollable(FrameNode* frameNode, bool scrollable)
823 {
824     CHECK_NULL_VOID(frameNode);
825     auto props = GetSwiperLayoutProperty(frameNode);
826     CHECK_NULL_VOID(props);
827     props->UpdateDisableSwipe(!scrollable);
828     auto tabPattern = frameNode->GetPattern<TabsPattern>();
829     CHECK_NULL_VOID(tabPattern);
830     tabPattern->SetIsDisableSwipe(!scrollable);
831 }
832 
SetTabBarWidth(FrameNode * frameNode,const Dimension & tabBarWidth)833 void TabsModelNG::SetTabBarWidth(FrameNode* frameNode, const Dimension& tabBarWidth)
834 {
835     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, BarWidth, tabBarWidth, frameNode);
836     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
837     CHECK_NULL_VOID(tabsNode);
838     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
839     CHECK_NULL_VOID(tabBarNode);
840     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
841     CHECK_NULL_VOID(tabBarLayoutProperty);
842     auto scaleProperty = ScaleProperty::CreateScaleProperty();
843     auto tabBarWidthToPx =
844         ConvertToPx(tabBarWidth, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Width());
845     if (LessNotEqual(tabBarWidthToPx.value_or(0.0), 0.0)) {
846         tabBarLayoutProperty->ClearUserDefinedIdealSize(true, false);
847     } else {
848         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(tabBarWidth), std::nullopt));
849     }
850     tabBarLayoutProperty->UpdateTabBarWidth(tabBarWidth);
851 }
852 
SetTabBarHeight(FrameNode * frameNode,const Dimension & tabBarHeight)853 void TabsModelNG::SetTabBarHeight(FrameNode* frameNode, const Dimension& tabBarHeight)
854 {
855     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TabsLayoutProperty, BarHeight, tabBarHeight, frameNode);
856     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
857     CHECK_NULL_VOID(tabsNode);
858     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
859     CHECK_NULL_VOID(tabBarNode);
860     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
861     CHECK_NULL_VOID(tabBarLayoutProperty);
862     auto scaleProperty = ScaleProperty::CreateScaleProperty();
863     auto tabBarHeightToPx = ConvertToPx(
864         tabBarHeight, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Height());
865     if (LessNotEqual(tabBarHeightToPx.value_or(0.0), 0.0)) {
866         tabBarLayoutProperty->ClearUserDefinedIdealSize(false, true);
867     } else {
868         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, NG::CalcLength(tabBarHeight)));
869     }
870     tabBarLayoutProperty->UpdateTabBarHeight(tabBarHeight);
871 }
872 
SetAnimationDuration(FrameNode * frameNode,float duration)873 void TabsModelNG::SetAnimationDuration(FrameNode* frameNode, float duration)
874 {
875     CHECK_NULL_VOID(frameNode);
876     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
877     CHECK_NULL_VOID(tabsNode);
878     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
879     CHECK_NULL_VOID(tabBarNode);
880     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
881     CHECK_NULL_VOID(tabBarPattern);
882     tabBarPattern->SetAnimationDuration(static_cast<int32_t>(duration));
883     if (static_cast<int32_t>(duration) < 0) {
884         return;
885     }
886     auto swiperPaintProperty = GetSwiperPaintProperty(frameNode);
887     CHECK_NULL_VOID(swiperPaintProperty);
888     swiperPaintProperty->UpdateDuration(static_cast<int32_t>(duration));
889 }
890 
SetScrollableBarModeOptions(FrameNode * frameNode,const ScrollableBarModeOptions & option)891 void TabsModelNG::SetScrollableBarModeOptions(FrameNode* frameNode, const ScrollableBarModeOptions& option)
892 {
893     CHECK_NULL_VOID(frameNode);
894     auto tabBarLayoutProperty = GetTabBarLayoutProperty(frameNode);
895     CHECK_NULL_VOID(tabBarLayoutProperty);
896     tabBarLayoutProperty->UpdateScrollableBarModeOptions(option);
897 }
898 
SetBarAdaptiveHeight(FrameNode * frameNode,bool barAdaptiveHeight)899 void TabsModelNG::SetBarAdaptiveHeight(FrameNode* frameNode, bool barAdaptiveHeight)
900 {
901     CHECK_NULL_VOID(frameNode);
902     auto tabBarLayoutProperty = GetTabBarLayoutProperty(frameNode);
903     CHECK_NULL_VOID(tabBarLayoutProperty);
904     tabBarLayoutProperty->UpdateBarAdaptiveHeight(barAdaptiveHeight);
905 }
906 
SetIsCustomAnimation(bool isCustom)907 void TabsModelNG::SetIsCustomAnimation(bool isCustom)
908 {
909     auto swiperLayoutProperty = GetSwiperLayoutProperty();
910     CHECK_NULL_VOID(swiperLayoutProperty);
911     swiperLayoutProperty->UpdateIsCustomAnimation(isCustom);
912     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
913     CHECK_NULL_VOID(tabsNode);
914     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
915     CHECK_NULL_VOID(tabPattern);
916     tabPattern->SetIsCustomAnimation(isCustom);
917 }
918 
SetOnCustomAnimation(TabsCustomAnimationEvent && onCustomAnimation)919 void TabsModelNG::SetOnCustomAnimation(TabsCustomAnimationEvent&& onCustomAnimation)
920 {
921     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
922     CHECK_NULL_VOID(tabsNode);
923     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
924     CHECK_NULL_VOID(swiperNode);
925     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
926     CHECK_NULL_VOID(swiperPattern);
927     swiperPattern->SetTabsCustomContentTransition(std::move(onCustomAnimation));
928 }
929 
SetClipEdge(FrameNode * frameNode,bool clipEdge)930 void TabsModelNG::SetClipEdge(FrameNode* frameNode, bool clipEdge)
931 {
932     CHECK_NULL_VOID(frameNode);
933     ViewAbstract::SetClipEdge(frameNode, clipEdge);
934     auto tabsChildren = frameNode->GetChildren();
935     for (const auto& child : tabsChildren) {
936         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
937         CHECK_NULL_VOID(childFrameNode);
938         auto renderContext = childFrameNode->GetRenderContext();
939         CHECK_NULL_VOID(renderContext);
940         renderContext->UpdateClipEdge(clipEdge);
941     }
942 }
943 
SetOnContentWillChange(std::function<bool (int32_t,int32_t)> && callback)944 void TabsModelNG::SetOnContentWillChange(std::function<bool(int32_t, int32_t)>&& callback)
945 {
946     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
947     CHECK_NULL_VOID(tabsNode);
948     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
949     CHECK_NULL_VOID(tabPattern);
950     tabPattern->SetInterceptStatus(true);
951     tabPattern->SetOnContentWillChange(std::move(callback));
952 }
953 
SetAnimateMode(TabAnimateMode mode)954 void TabsModelNG::SetAnimateMode(TabAnimateMode mode)
955 {
956     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
957     CHECK_NULL_VOID(tabsNode);
958     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
959     CHECK_NULL_VOID(tabPattern);
960     tabPattern->SetAnimateMode(mode);
961 }
962 
SetAnimateMode(FrameNode * frameNode,TabAnimateMode mode)963 void TabsModelNG::SetAnimateMode(FrameNode* frameNode, TabAnimateMode mode)
964 {
965     CHECK_NULL_VOID(frameNode);
966     auto tabsNode = AceType::DynamicCast<TabsNode>(frameNode);
967     CHECK_NULL_VOID(tabsNode);
968     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
969     CHECK_NULL_VOID(tabPattern);
970     tabPattern->SetAnimateMode(mode);
971 }
972 
SetEdgeEffect(EdgeEffect edgeEffect)973 void TabsModelNG::SetEdgeEffect(EdgeEffect edgeEffect)
974 {
975     auto swiperPaintProperty = GetSwiperPaintProperty();
976     CHECK_NULL_VOID(swiperPaintProperty);
977     swiperPaintProperty->UpdateEdgeEffect(edgeEffect);
978 }
979 
SetEdgeEffect(FrameNode * frameNode,int32_t edgeEffect)980 void TabsModelNG::SetEdgeEffect(FrameNode* frameNode, int32_t edgeEffect)
981 {
982     auto swiperPaintProperty = GetSwiperPaintProperty(frameNode);
983     CHECK_NULL_VOID(swiperPaintProperty);
984     swiperPaintProperty->UpdateEdgeEffect(static_cast<EdgeEffect>(edgeEffect));
985 }
986 } // namespace OHOS::Ace::NG
987