• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/tabs/tabs_model_ng.h"
17 
18 #include <type_traits>
19 
20 #include "base/memory/ace_type.h"
21 #include "base/memory/referenced.h"
22 #include "base/utils/utils.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components/swiper/swiper_controller.h"
25 #include "core/components_ng/base/group_node.h"
26 #include "core/components_ng/base/view_stack_processor.h"
27 #include "core/components_ng/pattern/divider/divider_layout_property.h"
28 #include "core/components_ng/pattern/divider/divider_pattern.h"
29 #include "core/components_ng/pattern/divider/divider_render_property.h"
30 #include "core/components_ng/pattern/image/image_pattern.h"
31 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
32 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
33 #include "core/components_ng/pattern/swiper/swiper_paint_property.h"
34 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
35 #include "core/components_ng/pattern/tabs/tab_bar_paint_property.h"
36 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
37 #include "core/components_ng/pattern/tabs/tabs_node.h"
38 #include "core/components_ng/pattern/tabs/tabs_pattern.h"
39 #include "core/components_ng/pattern/text/text_pattern.h"
40 #include "core/components_ng/property/measure_utils.h"
41 #include "core/components_v2/inspector/inspector_constants.h"
42 
43 namespace OHOS::Ace::NG {
44 namespace {
45 constexpr Dimension BAR_BLUR_RADIUS = 200.0_vp;
46 constexpr Dimension BAR_SATURATE = 1.3_vp;
47 } // namespace
48 
Create(BarPosition barPosition,int32_t index,const RefPtr<TabController> &,const RefPtr<SwiperController> & swiperController)49 void TabsModelNG::Create(BarPosition barPosition, int32_t index, const RefPtr<TabController>& /*tabController*/,
50     const RefPtr<SwiperController>& swiperController)
51 {
52     auto* stack = ViewStackProcessor::GetInstance();
53     auto nodeId = stack->ClaimNodeId();
54     auto tabsNode = GetOrCreateTabsNode(V2::TABS_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<TabsPattern>(); });
55 
56     bool hasSwiperNode = tabsNode->HasSwiperNode();
57     bool hasTabBarNode = tabsNode->HasTabBarNode();
58     bool hasDividerNode = tabsNode->HasDividerNode();
59     bool hasSelectedMaskNode = tabsNode->HasSelectedMaskNode();
60     bool hasUnselectedMaskNode = tabsNode->HasUnselectedMaskNode();
61     auto swiperId = tabsNode->GetSwiperId();
62     auto tabBarId = tabsNode->GetTabBarId();
63     auto dividerId = tabsNode->GetDividerId();
64     auto selectedMaskId = tabsNode->GetSelectedMaskId();
65     auto unselectedMaskId = tabsNode->GetUnselectedMaskId();
66 
67     // Create Swiper node to contain TabContent.
68     auto swiperNode = FrameNode::GetOrCreateFrameNode(
69         V2::SWIPER_ETS_TAG, swiperId, []() { return AceType::MakeRefPtr<SwiperPattern>(); });
70     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
71     swiperPaintProperty->UpdateEdgeEffect(EdgeEffect::SPRING);
72     auto pipelineContext = PipelineContext::GetCurrentContext();
73     CHECK_NULL_VOID(pipelineContext);
74     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
75     CHECK_NULL_VOID(tabTheme);
76     swiperPaintProperty->UpdateDuration(tabTheme->GetTabContentAnimationDuration());
77     swiperPaintProperty->UpdateCurve(TabBarPhysicalCurve);
78     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
79     swiperLayoutProperty->UpdateLoop(false);
80     swiperLayoutProperty->UpdateCachedCount(0);
81     swiperLayoutProperty->UpdateShowIndicator(false);
82     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
83     CHECK_NULL_VOID(swiperPattern);
84     auto controller = swiperController ? swiperController : swiperPattern->GetSwiperController();
85     if (!controller) {
86         controller = AceType::MakeRefPtr<SwiperController>();
87     }
88     swiperPattern->SetSwiperController(controller);
89 
90     auto dividerNode = FrameNode::GetOrCreateFrameNode(
91         V2::DIVIDER_ETS_TAG, dividerId, []() { return AceType::MakeRefPtr<DividerPattern>(); });
92 
93     // Create TabBar to contain TabBar of TabContent.
94     auto tabBarNode = FrameNode::GetOrCreateFrameNode(
95         V2::TAB_BAR_ETS_TAG, tabBarId, [controller]() { return AceType::MakeRefPtr<TabBarPattern>(controller); });
96 
97     auto selectedMaskNode = FrameNode::GetOrCreateFrameNode(
98         V2::COLUMN_ETS_TAG, selectedMaskId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
99 
100     auto unselectedMaskNode = FrameNode::GetOrCreateFrameNode(
101         V2::COLUMN_ETS_TAG, unselectedMaskId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
102 
103     if (!hasSwiperNode) {
104         swiperNode->MountToParent(tabsNode);
105     }
106     if (!hasDividerNode) {
107         dividerNode->MountToParent(tabsNode);
108     }
109     if (!hasTabBarNode) {
110         tabBarNode->MountToParent(tabsNode);
111     }
112     if (!hasSelectedMaskNode) {
113         selectedMaskNode->MountToParent(tabBarNode);
114         auto selectedImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
115             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
116         selectedImageNode->MountToParent(selectedMaskNode);
117         auto selectedMaskRenderContext = selectedMaskNode->GetRenderContext();
118         auto selectedMaskProperty = selectedMaskNode->GetLayoutProperty<LinearLayoutProperty>();
119         selectedMaskProperty->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
120         selectedMaskRenderContext->SetClipToBounds(true);
121     }
122     if (!hasUnselectedMaskNode) {
123         unselectedMaskNode->MountToParent(tabBarNode);
124         auto unselectedImageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
125             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
126         unselectedImageNode->MountToParent(unselectedMaskNode);
127         auto unselectedMaskRenderContext = unselectedMaskNode->GetRenderContext();
128         auto unselectedMaskProperty = unselectedMaskNode->GetLayoutProperty<LinearLayoutProperty>();
129         unselectedMaskProperty->UpdateCrossAxisAlign(FlexAlign::FLEX_START);
130         unselectedMaskRenderContext->SetClipToBounds(true);
131     }
132 
133     ViewStackProcessor::GetInstance()->Push(tabsNode);
134 
135     SetTabBarPosition(barPosition);
136     if (!hasTabBarNode) {
137         auto tabsFrameNode = AceType::DynamicCast<FrameNode>(tabsNode);
138         CHECK_NULL_VOID(tabsFrameNode);
139         auto tabsLayoutProperty = tabsFrameNode->GetLayoutProperty<TabsLayoutProperty>();
140         tabsLayoutProperty->UpdateIndex(index < 0 ? 0 : index);
141         return;
142     }
143     auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
144     auto preIndex = tabsLayoutProperty->GetIndexValue(0);
145     if ((index != preIndex) && (index >= 0)) {
146         SetIndex(index);
147         auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
148         tabBarPattern->SetMaskAnimationByCreate(true);
149         tabBarPattern->UpdateImageColor(index);
150     }
151 }
152 
SetTabBarPosition(BarPosition tabBarPosition)153 void TabsModelNG::SetTabBarPosition(BarPosition tabBarPosition)
154 {
155     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarPosition, tabBarPosition);
156 }
157 
SetTabBarMode(TabBarMode tabBarMode)158 void TabsModelNG::SetTabBarMode(TabBarMode tabBarMode)
159 {
160     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, TabBarMode, tabBarMode);
161     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
162     CHECK_NULL_VOID(tabBarLayoutProperty);
163     tabBarLayoutProperty->UpdateTabBarMode(tabBarMode);
164 }
165 
SetTabBarWidth(const Dimension & tabBarWidth)166 void TabsModelNG::SetTabBarWidth(const Dimension& tabBarWidth)
167 {
168     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarWidth, tabBarWidth);
169     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
170     CHECK_NULL_VOID(tabsNode);
171     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
172     CHECK_NULL_VOID(tabBarNode);
173     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
174     CHECK_NULL_VOID(tabBarLayoutProperty);
175     auto scaleProperty = ScaleProperty::CreateScaleProperty();
176     auto tabBarWidthToPx =
177         ConvertToPx(tabBarWidth, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Width());
178     if (LessNotEqual(tabBarWidthToPx.value_or(0.0), 0.0)) {
179         tabBarLayoutProperty->ClearUserDefinedIdealSize(true, false);
180     } else {
181         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(tabBarWidth), std::nullopt));
182     }
183     tabBarLayoutProperty->UpdateTabBarWidth(tabBarWidth);
184 }
185 
SetTabBarHeight(const Dimension & tabBarHeight)186 void TabsModelNG::SetTabBarHeight(const Dimension& tabBarHeight)
187 {
188     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarHeight, tabBarHeight);
189     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
190     CHECK_NULL_VOID(tabsNode);
191     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
192     CHECK_NULL_VOID(tabBarNode);
193     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
194     CHECK_NULL_VOID(tabBarLayoutProperty);
195     auto scaleProperty = ScaleProperty::CreateScaleProperty();
196     auto tabBarHeightToPx = ConvertToPx(
197         tabBarHeight, scaleProperty, tabBarLayoutProperty->GetLayoutConstraint()->percentReference.Height());
198     if (LessNotEqual(tabBarHeightToPx.value_or(0.0), 0.0)) {
199         tabBarLayoutProperty->ClearUserDefinedIdealSize(false, true);
200     } else {
201         tabBarLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, NG::CalcLength(tabBarHeight)));
202     }
203     tabBarLayoutProperty->UpdateTabBarHeight(tabBarHeight);
204 }
205 
SetBarAdaptiveHeight(bool barAdaptiveHeight)206 void TabsModelNG::SetBarAdaptiveHeight(bool barAdaptiveHeight)
207 {
208     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
209     CHECK_NULL_VOID(tabBarLayoutProperty);
210     tabBarLayoutProperty->UpdateBarAdaptiveHeight(barAdaptiveHeight);
211 }
212 
SetIsVertical(bool isVertical)213 void TabsModelNG::SetIsVertical(bool isVertical)
214 {
215     auto axis = isVertical ? Axis::VERTICAL : Axis::HORIZONTAL;
216     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Axis, axis);
217 
218     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
219     CHECK_NULL_VOID(tabBarLayoutProperty);
220     if (tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL) != axis) {
221         auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
222         CHECK_NULL_VOID(tabsNode);
223         auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
224         CHECK_NULL_VOID(tabBarNode);
225         auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
226         CHECK_NULL_VOID(tabBarPattern);
227         tabBarPattern->UpdateCurrentOffset(0.0f);
228     }
229     tabBarLayoutProperty->UpdateAxis(axis);
230     auto swiperLayoutProperty = GetSwiperLayoutProperty();
231     CHECK_NULL_VOID(swiperLayoutProperty);
232     swiperLayoutProperty->UpdateDirection(axis);
233 }
234 
SetIndex(int32_t index)235 void TabsModelNG::SetIndex(int32_t index)
236 {
237     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
238     CHECK_NULL_VOID(tabsNode);
239     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
240     CHECK_NULL_VOID(swiperNode);
241     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
242     CHECK_NULL_VOID(swiperLayoutProperty);
243     swiperLayoutProperty->UpdateIndex(index);
244     auto tabContentNum = swiperNode->TotalChildCount();
245     if (tabContentNum == 0) {
246         return;
247     }
248     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
249     CHECK_NULL_VOID(tabBarNode);
250     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
251     CHECK_NULL_VOID(tabBarPattern);
252     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
253     CHECK_NULL_VOID(tabBarLayoutProperty);
254     if (index > tabContentNum - 1 || index < 0) {
255         index = 0;
256     }
257     tabBarLayoutProperty->UpdateIndicator(index);
258     tabBarPattern->UpdateTextColor(index);
259     swiperLayoutProperty->UpdateIndex(index);
260     auto tabsFrameNode = AceType::DynamicCast<FrameNode>(tabsNode);
261     CHECK_NULL_VOID(tabsFrameNode);
262     auto tabsLayoutProperty = tabsFrameNode->GetLayoutProperty<TabsLayoutProperty>();
263     tabsLayoutProperty->UpdateIndex(index);
264     swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
265 }
266 
SetScrollable(bool scrollable)267 void TabsModelNG::SetScrollable(bool scrollable)
268 {
269     auto swiperPaintProperty = GetSwiperPaintProperty();
270     CHECK_NULL_VOID(swiperPaintProperty);
271     swiperPaintProperty->UpdateDisableSwipe(!scrollable);
272 }
273 
SetAnimationDuration(float duration)274 void TabsModelNG::SetAnimationDuration(float duration)
275 {
276     if (duration < 0) {
277         return;
278     }
279     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
280     CHECK_NULL_VOID(tabsNode);
281     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
282     CHECK_NULL_VOID(tabBarNode);
283     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
284     CHECK_NULL_VOID(tabBarPattern);
285     tabBarPattern->SetAnimationDuration(static_cast<int32_t>(duration));
286     auto swiperPaintProperty = GetSwiperPaintProperty();
287     CHECK_NULL_VOID(swiperPaintProperty);
288     swiperPaintProperty->UpdateDuration(static_cast<int32_t>(duration));
289 }
290 
SetFadingEdge(bool fadingEdge)291 void TabsModelNG::SetFadingEdge(bool fadingEdge)
292 {
293     auto tabBarPaintProperty = GetTabBarPaintProperty();
294     CHECK_NULL_VOID(tabBarPaintProperty);
295     tabBarPaintProperty->UpdateFadingEdge(fadingEdge);
296 }
297 
SetBarOverlap(bool barOverlap)298 void TabsModelNG::SetBarOverlap(bool barOverlap)
299 {
300     ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, BarOverlap, barOverlap);
301 
302     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
303     CHECK_NULL_VOID(tabsNode);
304     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
305     CHECK_NULL_VOID(tabBarNode);
306     auto tabBarRenderContext = tabBarNode->GetRenderContext();
307     CHECK_NULL_VOID(tabBarRenderContext);
308     if (barOverlap) {
309         tabBarRenderContext->UpdateBackBlurRadius(BAR_BLUR_RADIUS);
310         tabBarRenderContext->UpdateFrontSaturate(BAR_SATURATE);
311     } else {
312         tabBarRenderContext->UpdateBackBlurRadius(0.0_vp);
313         tabBarRenderContext->ResetFrontSaturate();
314     }
315     auto pipelineContext = PipelineContext::GetCurrentContext();
316     CHECK_NULL_VOID(pipelineContext);
317     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
318     CHECK_NULL_VOID(tabTheme);
319     auto defaultBgColorBlur = tabTheme->GetColorBottomTabSubBgBlur();
320     auto tabBarPaintProperty = GetTabBarPaintProperty();
321     CHECK_NULL_VOID(tabBarPaintProperty);
322     if (barOverlap && !tabBarPaintProperty->GetBarBackgroundColor().has_value()) {
323         tabBarRenderContext->UpdateBackgroundColor(defaultBgColorBlur);
324     } else {
325         tabBarRenderContext->UpdateBackgroundColor(
326             tabBarPaintProperty->GetBarBackgroundColor().value_or(Color::BLACK.BlendOpacity(0.0f)));
327     }
328 }
329 
SetOnChange(std::function<void (const BaseEventInfo *)> && onChange)330 void TabsModelNG::SetOnChange(std::function<void(const BaseEventInfo*)>&& onChange)
331 {
332     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
333     CHECK_NULL_VOID(tabsNode);
334     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
335     CHECK_NULL_VOID(tabPattern);
336     tabPattern->SetOnChangeEvent(std::move(onChange));
337 }
338 
SetOnTabBarClick(std::function<void (const BaseEventInfo *)> && onTabBarClick)339 void TabsModelNG::SetOnTabBarClick(std::function<void(const BaseEventInfo*)>&& onTabBarClick)
340 {
341     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
342     CHECK_NULL_VOID(tabsNode);
343     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
344     CHECK_NULL_VOID(tabPattern);
345     tabPattern->SetOnTabBarClickEvent(std::move(onTabBarClick));
346 }
347 
SetDivider(const TabsItemDivider & divider)348 void TabsModelNG::SetDivider(const TabsItemDivider& divider)
349 {
350     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
351     CHECK_NULL_VOID(tabsNode);
352     auto dividerNode = AceType::DynamicCast<FrameNode>(tabsNode->GetChildAtIndex(1));
353     CHECK_NULL_VOID(dividerNode);
354     auto dividerRenderContext = dividerNode->GetRenderContext();
355     CHECK_NULL_VOID(dividerRenderContext);
356     if (divider.isNull) {
357         dividerRenderContext->UpdateOpacity(0.0f);
358         auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
359         CHECK_NULL_VOID(tabsLayoutProperty);
360         auto currentDivider = tabsLayoutProperty->GetDivider().value_or(TabsItemDivider());
361         currentDivider.strokeWidth = Dimension(1.0f);
362         currentDivider.isNull = true;
363         ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, currentDivider);
364     } else {
365         dividerRenderContext->UpdateOpacity(1.0f);
366         ACE_UPDATE_LAYOUT_PROPERTY(TabsLayoutProperty, Divider, divider);
367     }
368 }
369 
SetBarBackgroundColor(const Color & backgroundColor)370 void TabsModelNG::SetBarBackgroundColor(const Color& backgroundColor)
371 {
372     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
373     CHECK_NULL_VOID(tabsNode);
374     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
375     CHECK_NULL_VOID(tabBarNode);
376     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
377     CHECK_NULL_VOID(tabBarPaintProperty);
378     tabBarPaintProperty->UpdateBarBackgroundColor(backgroundColor);
379     auto tabBarRenderContext = tabBarNode->GetRenderContext();
380     CHECK_NULL_VOID(tabBarRenderContext);
381     tabBarRenderContext->UpdateBackgroundColor(backgroundColor);
382 }
383 
GetTabBarLayoutProperty()384 RefPtr<TabBarLayoutProperty> TabsModelNG::GetTabBarLayoutProperty()
385 {
386     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
387     CHECK_NULL_RETURN(tabsNode, nullptr);
388     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
389     CHECK_NULL_RETURN(tabBarNode, nullptr);
390     auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
391     CHECK_NULL_RETURN(tabBarLayoutProperty, nullptr);
392     return tabBarLayoutProperty;
393 }
394 
GetTabBarPaintProperty()395 RefPtr<TabBarPaintProperty> TabsModelNG::GetTabBarPaintProperty()
396 {
397     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
398     CHECK_NULL_RETURN(tabsNode, nullptr);
399     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
400     CHECK_NULL_RETURN(tabBarNode, nullptr);
401     auto tabBarPaintProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
402     CHECK_NULL_RETURN(tabBarPaintProperty, nullptr);
403     return tabBarPaintProperty;
404 }
405 
GetSwiperLayoutProperty()406 RefPtr<SwiperLayoutProperty> TabsModelNG::GetSwiperLayoutProperty()
407 {
408     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
409     CHECK_NULL_RETURN(tabsNode, nullptr);
410     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
411     CHECK_NULL_RETURN(swiperNode, nullptr);
412     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
413     CHECK_NULL_RETURN(swiperLayoutProperty, nullptr);
414     return swiperLayoutProperty;
415 }
416 
GetSwiperPaintProperty()417 RefPtr<SwiperPaintProperty> TabsModelNG::GetSwiperPaintProperty()
418 {
419     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
420     CHECK_NULL_RETURN(tabsNode, nullptr);
421     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
422     CHECK_NULL_RETURN(swiperNode, nullptr);
423     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
424     CHECK_NULL_RETURN(swiperPaintProperty, nullptr);
425     return swiperPaintProperty;
426 }
427 
Pop()428 void TabsModelNG::Pop()
429 {
430     auto tabsNode = AceType::DynamicCast<TabsNode>(ViewStackProcessor::GetInstance()->GetMainFrameNode());
431     CHECK_NULL_VOID(tabsNode);
432     auto tabsLayoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
433     auto index = tabsLayoutProperty->GetIndexValue(0);
434     auto tabBarNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabBar());
435     CHECK_NULL_VOID(tabBarNode);
436     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
437     CHECK_NULL_VOID(tabBarPattern);
438     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
439     CHECK_NULL_VOID(tabBarLayoutProperty);
440     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
441     CHECK_NULL_VOID(swiperNode);
442     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
443     CHECK_NULL_VOID(swiperLayoutProperty);
444 
445     auto tabBarPosition = tabsLayoutProperty->GetTabBarPosition().value_or(BarPosition::START);
446     auto tabsFocusNode = tabsNode->GetFocusHub();
447     CHECK_NULL_VOID(tabsFocusNode);
448     auto tabBarFocusNode = tabBarNode->GetFocusHub();
449     CHECK_NULL_VOID(tabBarFocusNode);
450     if (tabBarPosition == BarPosition::START) {
451         if (tabsFocusNode->IsCurrentFocus()) {
452             tabBarFocusNode->RequestFocusImmediately();
453         } else {
454             tabsFocusNode->SetLastWeakFocusNode(AceType::WeakClaim(AceType::RawPtr(tabBarFocusNode)));
455         }
456     }
457 
458     auto tabContentNum = swiperNode->TotalChildCount();
459     if (index > tabContentNum - 1 || index < 0) {
460         index = 0;
461     }
462     tabBarLayoutProperty->UpdateIndicator(index);
463     tabBarPattern->UpdateTextColor(index);
464     swiperLayoutProperty->UpdateIndex(index);
465 
466     tabBarNode->MarkModifyDone();
467     tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
468     auto dividerNode = AceType::DynamicCast<FrameNode>(tabsNode->GetDivider());
469     CHECK_NULL_VOID(dividerNode);
470     auto layoutProperty = tabsNode->GetLayoutProperty<TabsLayoutProperty>();
471     CHECK_NULL_VOID(layoutProperty);
472 
473     auto axis = layoutProperty->GetAxis().value_or((Axis::HORIZONTAL));
474     TabsItemDivider defaultDivider;
475     auto divider = layoutProperty->GetDivider().value_or(defaultDivider);
476     auto dividerColor = divider.color;
477     auto dividerStrokeWidth = divider.strokeWidth;
478 
479     auto dividerHub = dividerNode->GetEventHub<EventHub>();
480     CHECK_NULL_VOID(dividerHub);
481 
482     auto dividerRenderProperty = dividerNode->GetPaintProperty<DividerRenderProperty>();
483     CHECK_NULL_VOID(dividerRenderProperty);
484     dividerRenderProperty->UpdateDividerColor(dividerColor);
485 
486     auto dividerLayoutProperty = dividerNode->GetLayoutProperty<DividerLayoutProperty>();
487     CHECK_NULL_VOID(dividerLayoutProperty);
488     dividerLayoutProperty->UpdateVertical(axis == Axis::VERTICAL);
489     dividerLayoutProperty->UpdateStrokeWidth(dividerStrokeWidth);
490     CHECK_NULL_VOID(dividerNode);
491     dividerNode->MarkModifyDone();
492 
493     swiperNode->MarkModifyDone();
494     swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
495 
496     ViewStackProcessor::GetInstance()->PopContainer();
497 }
498 
GetOrCreateTabsNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)499 RefPtr<TabsNode> TabsModelNG::GetOrCreateTabsNode(
500     const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
501 {
502     auto tabsNode = ElementRegister::GetInstance()->GetSpecificItemById<TabsNode>(nodeId);
503     if (tabsNode) {
504         if (tabsNode->GetTag() == tag) {
505             return tabsNode;
506         }
507         ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
508         auto parent = tabsNode->GetParent();
509         if (parent) {
510             parent->RemoveChild(tabsNode);
511         }
512     }
513 
514     auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
515     tabsNode = AceType::MakeRefPtr<TabsNode>(tag, nodeId, pattern, false);
516     tabsNode->InitializePatternAndContext();
517     ElementRegister::GetInstance()->AddUINode(tabsNode);
518     return tabsNode;
519 }
520 
SetOnChangeEvent(std::function<void (const BaseEventInfo *)> && onChangeEvent)521 void TabsModelNG::SetOnChangeEvent(std::function<void(const BaseEventInfo*)>&& onChangeEvent)
522 {
523     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
524     CHECK_NULL_VOID(tabsNode);
525     auto tabPattern = tabsNode->GetPattern<TabsPattern>();
526     CHECK_NULL_VOID(tabPattern);
527     tabPattern->SetOnIndexChangeEvent(std::move(onChangeEvent));
528 }
529 
SetClipEdge(bool clipEdge)530 void TabsModelNG::SetClipEdge(bool clipEdge)
531 {
532     auto tabsNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
533     CHECK_NULL_VOID(tabsNode);
534     auto tabsRenderContext = tabsNode->GetRenderContext();
535     CHECK_NULL_VOID(tabsRenderContext);
536     tabsRenderContext->UpdateClipEdge(clipEdge);
537     auto tabsChildren = tabsNode->GetChildren();
538     for (const auto& child : tabsChildren) {
539         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
540         CHECK_NULL_VOID(childFrameNode);
541         auto renderContext = childFrameNode->GetRenderContext();
542         CHECK_NULL_VOID(renderContext);
543         renderContext->UpdateClipEdge(clipEdge);
544     }
545 }
546 
SetScrollableBarModeOptions(const ScrollableBarModeOptions & option)547 void TabsModelNG::SetScrollableBarModeOptions(const ScrollableBarModeOptions& option)
548 {
549     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
550     CHECK_NULL_VOID(tabBarLayoutProperty);
551     tabBarLayoutProperty->UpdateScrollableBarModeOptions(option);
552 }
553 
SetBarGridAlign(const BarGridColumnOptions & BarGridColumnOptions)554 void TabsModelNG::SetBarGridAlign(const BarGridColumnOptions& BarGridColumnOptions)
555 {
556     auto tabBarLayoutProperty = GetTabBarLayoutProperty();
557     CHECK_NULL_VOID(tabBarLayoutProperty);
558     tabBarLayoutProperty->UpdateBarGridAlign(BarGridColumnOptions);
559 }
560 } // namespace OHOS::Ace::NG
561