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