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/tab_content_model_ng.h"
17 #include <optional>
18
19 #include "base/memory/ace_type.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/utils.h"
22 #include "core/components/tab_bar/tab_theme.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/view_stack_processor.h"
25 #include "core/components_ng/pattern/image/image_layout_property.h"
26 #include "core/components_ng/pattern/image/image_pattern.h"
27 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
28 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
29 #include "core/components_ng/pattern/tabs/tab_bar_item_pattern.h"
30 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
31 #include "core/components_ng/pattern/tabs/tab_content_event_hub.h"
32 #include "core/components_ng/pattern/tabs/tab_content_node.h"
33 #include "core/components_ng/pattern/tabs/tab_content_pattern.h"
34 #include "core/components_ng/pattern/tabs/tabs_node.h"
35 #include "core/components_ng/pattern/text/text_pattern.h"
36 #include "core/components_ng/pattern/symbol/constants.h"
37 #include "core/components_ng/pattern/symbol/symbol_effect_options.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39
40 namespace OHOS::Ace::NG {
41 namespace {
42 constexpr uint16_t PIXEL_ROUND = static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_START) |
43 static_cast<uint16_t>(PixelRoundPolicy::FORCE_FLOOR_TOP) |
44 static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_END) |
45 static_cast<uint16_t>(PixelRoundPolicy::FORCE_CEIL_BOTTOM);
46 constexpr uint32_t DEFAULT_RENDERING_STRATEGY = 2;
47 const auto MASK_COUNT = 2;
48 }
49
Create(std::function<void ()> && deepRenderFunc)50 void TabContentModelNG::Create(std::function<void()>&& deepRenderFunc)
51 {
52 auto* stack = ViewStackProcessor::GetInstance();
53 auto nodeId = stack->ClaimNodeId();
54 auto deepRender = [nodeId, deepRenderFunc = std::move(deepRenderFunc)]() -> RefPtr<UINode> {
55 CHECK_NULL_RETURN(deepRenderFunc, nullptr);
56 ScopedViewStackProcessor scopedViewStackProcessor;
57 deepRenderFunc();
58 auto deepChild = ViewStackProcessor::GetInstance()->Finish();
59 auto parent = FrameNode::GetFrameNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId);
60 if (deepChild && parent) {
61 deepChild->MountToParent(parent);
62 }
63 return deepChild;
64 };
65 ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId);
66 auto frameNode = TabContentNode::GetOrCreateTabContentNode(V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId,
67 [shallowBuilder = AceType::MakeRefPtr<ShallowBuilder>(std::move(deepRender))]() {
68 return AceType::MakeRefPtr<TabContentPattern>(shallowBuilder);
69 });
70 stack->Push(frameNode);
71 auto pipelineContext = PipelineContext::GetCurrentContext();
72 CHECK_NULL_VOID(pipelineContext);
73 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
74 CHECK_NULL_VOID(tabTheme);
75 SetTabBar(tabTheme->GetDefaultTabBarName(), "", std::nullopt, nullptr, true); // Set default tab bar.
76 ACE_UPDATE_LAYOUT_PROPERTY(TabContentLayoutProperty, Text, tabTheme->GetDefaultTabBarName());
77 }
78
Create()79 void TabContentModelNG::Create()
80 {
81 auto* stack = ViewStackProcessor::GetInstance();
82 int32_t nodeId = stack->ClaimNodeId();
83 ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId);
84 auto frameNode = TabContentNode::GetOrCreateTabContentNode(
85 V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<TabContentPattern>(nullptr); });
86 stack->Push(frameNode);
87 auto pipelineContext = PipelineContext::GetCurrentContext();
88 CHECK_NULL_VOID(pipelineContext);
89 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
90 CHECK_NULL_VOID(tabTheme);
91 SetTabBar(tabTheme->GetDefaultTabBarName(), "", std::nullopt, nullptr, true); // Set default tab bar.
92 ACE_UPDATE_LAYOUT_PROPERTY(TabContentLayoutProperty, Text, tabTheme->GetDefaultTabBarName());
93 }
94
CreateFrameNode(int32_t nodeId)95 RefPtr<FrameNode> TabContentModelNG::CreateFrameNode(int32_t nodeId)
96 {
97 auto frameNode = TabContentNode::GetOrCreateTabContentNode(
98 V2::TAB_CONTENT_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<TabContentPattern>(nullptr); });
99 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
100 CHECK_NULL_RETURN(pipelineContext, nullptr);
101 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
102 CHECK_NULL_RETURN(tabTheme, nullptr);
103 auto layout = frameNode->GetLayoutProperty<TabContentLayoutProperty>();
104 CHECK_NULL_RETURN(layout, nullptr);
105 auto text = tabTheme->GetDefaultTabBarName();
106 layout->UpdateText(text);
107 layout->UpdateIcon("");
108 auto pattern = frameNode->GetPattern<TabContentPattern>();
109 CHECK_NULL_RETURN(pattern, nullptr);
110 pattern->SetTabBar(text, "", std::nullopt, nullptr);
111 return frameNode;
112 }
113
Pop()114 void TabContentModelNG::Pop()
115 {
116 auto tabContent = AceType::Claim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
117 AddTabBarItem(tabContent, DEFAULT_NODE_SLOT, true);
118 NG::ViewStackProcessor::GetInstance()->PopContainer();
119 }
120
FindTabsNode(const RefPtr<UINode> & tabContent)121 RefPtr<TabsNode> TabContentModelNG::FindTabsNode(const RefPtr<UINode>& tabContent)
122 {
123 CHECK_NULL_RETURN(tabContent, nullptr);
124 RefPtr<UINode> parent = tabContent->GetParent();
125
126 while (parent) {
127 if (AceType::InstanceOf<TabsNode>(parent)) {
128 return AceType::DynamicCast<TabsNode>(parent);
129 }
130 parent = parent->GetParent();
131 }
132 return nullptr;
133 }
134
AddTabBarItem(const RefPtr<UINode> & tabContent,int32_t position,bool update)135 void TabContentModelNG::AddTabBarItem(const RefPtr<UINode>& tabContent, int32_t position, bool update)
136 {
137 CHECK_NULL_VOID(tabContent);
138 auto tabContentId = tabContent->GetId();
139
140 auto tabContentNode = AceType::DynamicCast<TabContentNode>(tabContent);
141 CHECK_NULL_VOID(tabContentNode);
142
143 if (update && !tabContentNode->HasTabBarItemId()) {
144 return;
145 }
146
147 auto tabsNode = FindTabsNode(tabContent);
148 CHECK_NULL_VOID(tabsNode);
149 auto tabBarNode = tabsNode->GetTabBar();
150 CHECK_NULL_VOID(tabBarNode);
151 auto tabContentPattern = tabContentNode->GetPattern<TabContentPattern>();
152 CHECK_NULL_VOID(tabContentPattern);
153 const auto& tabBarParam = tabContentPattern->GetTabBarParam();
154
155 // Create column node to contain image and text or builder.
156 auto columnNode = FrameNode::GetOrCreateFrameNode(V2::COLUMN_ETS_TAG, tabContentNode->GetTabBarItemId(),
157 []() { return AceType::MakeRefPtr<TabBarItemPattern>(); });
158 auto pipelineContext = tabsNode->GetContext();
159 CHECK_NULL_VOID(pipelineContext);
160 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
161 CHECK_NULL_VOID(tabTheme);
162 auto linearLayoutProperty = columnNode->GetLayoutProperty<LinearLayoutProperty>();
163 CHECK_NULL_VOID(linearLayoutProperty);
164 linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER);
165 linearLayoutProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
166 linearLayoutProperty->UpdateSpace(tabTheme->GetBottomTabBarSpace());
167 linearLayoutProperty->UpdatePixelRound(PIXEL_ROUND);
168 auto columnRenderContext = columnNode->GetRenderContext();
169 CHECK_NULL_VOID(columnRenderContext);
170 columnRenderContext->UpdateClipEdge(true);
171 auto tabBarFrameNode = AceType::DynamicCast<FrameNode>(tabBarNode);
172 CHECK_NULL_VOID(tabBarFrameNode);
173 auto tabBarPattern = tabBarFrameNode->GetPattern<TabBarPattern>();
174 CHECK_NULL_VOID(tabBarPattern);
175 tabBarPattern->SetTabBarStyle(tabBarParam.GetTabBarStyle());
176 tabBarPattern->AddTabBarItemClickEvent(columnNode);
177 auto selectedMode = tabContentPattern->GetSelectedMode();
178 auto indicatorStyle = tabContentPattern->GetIndicatorStyle();
179 auto boardStyle = tabContentPattern->GetBoardStyle();
180 auto bottomTabBarStyle = tabContentPattern->GetBottomTabBarStyle();
181 auto padding = tabContentPattern->GetPadding();
182 auto tabLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
183 CHECK_NULL_VOID(tabLayoutProperty);
184 auto isRTL = tabLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
185 if (isRTL && tabContentPattern->GetUseLocalizedPadding()) {
186 PaddingProperty paddingRtl;
187 paddingRtl.left = padding.right;
188 paddingRtl.right = padding.left;
189 paddingRtl.top = padding.top;
190 paddingRtl.bottom = padding.bottom;
191 padding = paddingRtl;
192 }
193
194 if (tabBarParam.GetTabBarStyle() == TabBarStyle::BOTTOMTABBATSTYLE) {
195 if (bottomTabBarStyle.layoutMode == LayoutMode::HORIZONTAL) {
196 linearLayoutProperty->UpdateFlexDirection(FlexDirection::ROW);
197 linearLayoutProperty->UpdateSpace(tabTheme->GetHorizontalBottomTabBarSpace());
198 linearLayoutProperty->UpdateCrossAxisAlign(bottomTabBarStyle.verticalAlign);
199 linearLayoutProperty->SetIsVertical(false);
200 } else {
201 linearLayoutProperty->UpdateFlexDirection(FlexDirection::COLUMN);
202 linearLayoutProperty->UpdateSpace(tabTheme->GetBottomTabBarSpace());
203 linearLayoutProperty->UpdateMainAxisAlign(bottomTabBarStyle.verticalAlign);
204 linearLayoutProperty->SetIsVertical(true);
205 }
206 }
207
208 auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
209 CHECK_NULL_VOID(swiperNode);
210 auto myIndex = swiperNode->GetChildFlatIndex(tabContentId).second;
211
212 tabBarPattern->SetTabBarStyle(tabBarParam.GetTabBarStyle(), myIndex);
213 tabBarPattern->SetBottomTabBarStyle(bottomTabBarStyle, myIndex);
214 auto labelStyle = tabContentPattern->GetLabelStyle();
215 tabBarPattern->SetLabelStyle(columnNode->GetId(), labelStyle);
216 auto iconStyle = tabContentPattern->GetIconStyle();
217 tabBarPattern->SetIconStyle(iconStyle, myIndex);
218 auto symbol = tabContentPattern->GetSymbol();
219 tabBarPattern->SetSymbol(symbol, myIndex);
220 auto tabBarStyle = tabContentPattern->GetTabBarStyle();
221 if (tabBarStyle == TabBarStyle::SUBTABBATSTYLE) {
222 auto renderContext = columnNode->GetRenderContext();
223 CHECK_NULL_VOID(renderContext);
224 BorderRadiusProperty borderRadiusProperty;
225 borderRadiusProperty.SetRadius(boardStyle.borderRadius);
226 renderContext->UpdateBorderRadius(borderRadiusProperty);
227 }
228 if (tabBarStyle != TabBarStyle::SUBTABBATSTYLE) {
229 indicatorStyle.marginTop = 0.0_vp;
230 }
231 tabBarPattern->SetSelectedMode(selectedMode, myIndex);
232 tabBarPattern->SetIndicatorStyle(indicatorStyle, myIndex);
233
234 // Create tab bar with builder.
235 if (tabBarParam.HasBuilder()) {
236 ScopedViewStackProcessor builderViewStackProcessor;
237 tabBarParam.ExecuteBuilder();
238 auto builderNode = ViewStackProcessor::GetInstance()->Finish();
239 if (static_cast<int32_t>(columnNode->GetChildren().size()) != 0) {
240 columnNode->Clean();
241 }
242 if (builderNode) {
243 builderNode->MountToParent(columnNode);
244 }
245 auto oldColumnNode = tabsNode->GetBuilderByContentId(tabContentId, columnNode);
246 if (!oldColumnNode) {
247 auto index = std::clamp(myIndex, 0, static_cast<int32_t>(tabBarNode->GetChildren().size()) - MASK_COUNT);
248 columnNode->MountToParent(tabBarNode, index);
249 } else {
250 tabBarNode->ReplaceChild(oldColumnNode, columnNode);
251 }
252 columnNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
253 tabBarPattern->AddTabBarItemType(columnNode->GetId(), true);
254 tabBarPattern->SetIsExecuteBuilder(true);
255 tabBarFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
256 return;
257 }
258
259 // Create text node and image node.
260 RefPtr<FrameNode> textNode;
261 RefPtr<FrameNode> iconNode;
262 auto layoutProperty = columnNode->GetLayoutProperty();
263 CHECK_NULL_VOID(layoutProperty);
264 if (tabBarStyle == TabBarStyle::SUBTABBATSTYLE || tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE) {
265 layoutProperty->UpdatePadding(padding);
266 auto accessibilityProperty = columnNode->GetAccessibilityProperty<AccessibilityProperty>();
267 accessibilityProperty->SetAccessibilityGroup(true);
268 auto id = tabContentPattern->GetId();
269 columnNode->UpdateInspectorId(id);
270 } else {
271 auto tabBarItemPadding = tabTheme->GetSubTabItemPadding();
272 layoutProperty->UpdatePadding({ CalcLength(tabBarItemPadding), CalcLength(tabBarItemPadding),
273 CalcLength(tabBarItemPadding), CalcLength(tabBarItemPadding) });
274 }
275
276 bool isFrameNode = false;
277 if (static_cast<int32_t>(columnNode->GetChildren().size()) == 0) {
278 if (tabBarParam.GetSymbol().has_value()) {
279 iconNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
280 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
281 } else {
282 iconNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
283 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
284 }
285 if (tabBarStyle == TabBarStyle::SUBTABBATSTYLE && tabContentPattern->HasSubTabBarStyleNode()) {
286 isFrameNode = true;
287 textNode = tabContentPattern->FireCustomStyleNode();
288 } else {
289 textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
290 []() { return AceType::MakeRefPtr<TextPattern>(); });
291 }
292 CHECK_NULL_VOID(textNode);
293 CHECK_NULL_VOID(iconNode);
294 auto index = std::clamp(position, 0, static_cast<int32_t>(tabBarNode->GetChildren().size()) - MASK_COUNT);
295 columnNode->MountToParent(tabBarNode, index);
296 iconNode->MountToParent(columnNode);
297 textNode->MountToParent(columnNode);
298 } else {
299 if (tabBarStyle == TabBarStyle::SUBTABBATSTYLE && tabContentPattern->HasSubTabBarStyleNode()) {
300 isFrameNode = true;
301 auto builderNode = tabContentPattern->FireCustomStyleNode();
302 columnNode->ReplaceChild(AceType::DynamicCast<FrameNode>(columnNode->GetChildren().back()), builderNode);
303 }
304 auto oldIcon = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
305 CHECK_NULL_VOID(oldIcon);
306 if (tabBarParam.GetSymbol().has_value() && oldIcon->GetTag() != V2::SYMBOL_ETS_TAG) {
307 auto icon = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
308 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
309 columnNode->ReplaceChild(oldIcon, icon);
310 } else if (!tabBarParam.GetIcon().empty() && oldIcon->GetTag() != V2::IMAGE_ETS_TAG) {
311 auto icon = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG,
312 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
313 columnNode->ReplaceChild(oldIcon, icon);
314 }
315 iconNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
316 textNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().back());
317 }
318 CHECK_NULL_VOID(textNode);
319 CHECK_NULL_VOID(iconNode);
320
321 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
322 CHECK_NULL_VOID(swiperPattern);
323 auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
324 CHECK_NULL_VOID(swiperLayoutProperty);
325 int32_t indicator = swiperLayoutProperty->GetIndexValue(0);
326 int32_t totalCount = swiperPattern->TotalCount();
327 if (indicator > totalCount - 1 || indicator < 0) {
328 indicator = 0;
329 }
330 tabBarPattern->UpdateSubTabBoard(indicator);
331 // Update property of text.
332 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
333 CHECK_NULL_VOID(textLayoutProperty);
334 auto tabBarLayoutProperty = tabBarPattern->GetLayoutProperty<TabBarLayoutProperty>();
335 CHECK_NULL_VOID(tabBarLayoutProperty);
336 auto axis = tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
337 if ((!swiperPattern->IsUseCustomAnimation() || !swiperPattern->GetCustomAnimationToIndex().has_value()) &&
338 !isFrameNode) {
339 if (myIndex == indicator) {
340 if (labelStyle.selectedColor.has_value()) {
341 textLayoutProperty->UpdateTextColor(labelStyle.selectedColor.value());
342 } else {
343 selectedMode == SelectedMode::BOARD && axis == Axis::HORIZONTAL ?
344 textLayoutProperty->UpdateTextColor(tabTheme->GetSubTabBoardTextOnColor()) :
345 textLayoutProperty->UpdateTextColor(tabTheme->GetSubTabTextOnColor());
346 }
347 } else {
348 if (labelStyle.unselectedColor.has_value()) {
349 textLayoutProperty->UpdateTextColor(labelStyle.unselectedColor.value());
350 } else {
351 textLayoutProperty->UpdateTextColor(tabTheme->GetSubTabTextOffColor());
352 }
353 }
354 }
355
356 auto textRenderContext = textNode->GetRenderContext();
357 CHECK_NULL_VOID(textRenderContext);
358 textRenderContext->UpdateClipEdge(true);
359 if (!isFrameNode) {
360 textLayoutProperty->UpdateContent(tabBarParam.GetText());
361 textLayoutProperty->UpdateFontSize(tabTheme->GetSubTabTextDefaultFontSize());
362 textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
363 }
364 if (!isFrameNode) {
365 textLayoutProperty->UpdateMaxLines(1);
366 textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
367 }
368 if (tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE) {
369 textLayoutProperty->UpdateFlexShrink(1.0f);
370 }
371
372 if (!tabBarParam.GetIcon().empty() || tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE) {
373 textLayoutProperty->UpdateFontSize(tabTheme->GetBottomTabTextSize());
374 }
375 if (tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE) {
376 textLayoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
377 } else if (tabBarStyle == TabBarStyle::SUBTABBATSTYLE && !isFrameNode) {
378 textLayoutProperty->UpdateFontWeight(myIndex == indicator ? FontWeight::MEDIUM : FontWeight::NORMAL);
379 }
380 if (tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE && bottomTabBarStyle.layoutMode == LayoutMode::HORIZONTAL) {
381 textLayoutProperty->UpdateTextAlign(TextAlign::LEFT);
382 if (!labelStyle.fontSize.has_value() &&
383 Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
384 textLayoutProperty->UpdateFontSize(tabTheme->GetBottomTabHorizontalTextSize());
385 }
386 }
387 if (!isFrameNode) {
388 UpdateLabelStyle(labelStyle, textLayoutProperty);
389 }
390
391 // Update property of image/symbol.
392 if (tabBarParam.GetSymbol().has_value()) {
393 auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
394 CHECK_NULL_VOID(symbolProperty);
395 UpdateDefaultSymbol(tabTheme, symbolProperty);
396 auto modifierOnApply = tabBarParam.GetSymbol().value().onApply;
397 if (myIndex == indicator) {
398 tabBarPattern->SetImageColorOnIndex(indicator);
399 symbolProperty->UpdateSymbolColorList({tabTheme->GetBottomTabSymbolOn()});
400 if (modifierOnApply != nullptr) {
401 modifierOnApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)), "normal");
402 UpdateDefaultSymbol(tabTheme, symbolProperty);
403 symbolProperty->UpdateSymbolColorList({tabTheme->GetBottomTabSymbolOn()});
404 }
405 if (modifierOnApply != nullptr && tabBarParam.GetSymbol().value().selectedFlag) {
406 modifierOnApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)),
407 "selected");
408 UpdateSymbolEffect(symbolProperty, false);
409 }
410 } else {
411 symbolProperty->UpdateSymbolColorList({tabTheme->GetBottomTabSymbolOff()});
412 if (modifierOnApply != nullptr) {
413 modifierOnApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)), "normal");
414 UpdateSymbolEffect(symbolProperty, false);
415 }
416 }
417 } else {
418 auto imageProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
419 CHECK_NULL_VOID(imageProperty);
420 if (!tabBarParam.GetIcon().empty() || tabBarStyle == TabBarStyle::BOTTOMTABBATSTYLE) {
421 imageProperty->UpdateUserDefinedIdealSize(CalcSize(
422 NG::CalcLength(tabTheme->GetBottomTabImageSize()), NG::CalcLength(tabTheme->GetBottomTabImageSize())));
423 } else {
424 imageProperty->UpdateUserDefinedIdealSize(CalcSize());
425 }
426 ImageSourceInfo imageSourceInfo(tabBarParam.GetIcon());
427 auto imagePaintProperty = iconNode->GetPaintProperty<ImageRenderProperty>();
428 CHECK_NULL_VOID(imagePaintProperty);
429 if (imageSourceInfo.IsSvg() && myIndex == indicator) {
430 tabBarPattern->SetImageColorOnIndex(indicator);
431 if (iconStyle.selectedColor.has_value()) {
432 imagePaintProperty->UpdateSvgFillColor(iconStyle.selectedColor.value());
433 } else {
434 imagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOn());
435 }
436 }
437 if (imageSourceInfo.IsSvg() && myIndex != indicator) {
438 if (iconStyle.unselectedColor.has_value()) {
439 imagePaintProperty->UpdateSvgFillColor(iconStyle.unselectedColor.value());
440 } else {
441 imagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOff());
442 }
443 }
444 imageProperty->UpdateImageSourceInfo(imageSourceInfo);
445 }
446 columnNode->MarkModifyDone();
447 textNode->MarkModifyDone();
448 textNode->MarkDirtyNode();
449 iconNode->MarkModifyDone();
450 tabBarPattern->AddTabBarItemType(columnNode->GetId(), false);
451 tabBarFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
452 }
453
RemoveTabBarItem(const RefPtr<TabContentNode> & tabContentNode)454 void TabContentModelNG::RemoveTabBarItem(const RefPtr<TabContentNode>& tabContentNode)
455 {
456 CHECK_NULL_VOID(tabContentNode);
457 if (!tabContentNode->HasTabBarItemId()) {
458 return;
459 }
460
461 auto tabBarItemId = tabContentNode->GetTabBarItemId();
462 auto tabBarItemNode = ElementRegister::GetInstance()->GetUINodeById(tabBarItemId);
463 CHECK_NULL_VOID(tabBarItemNode);
464 auto tabBarNode = tabBarItemNode->GetParent();
465 CHECK_NULL_VOID(tabBarNode);
466 auto tabBarFrameNode = AceType::DynamicCast<FrameNode>(tabBarNode);
467 CHECK_NULL_VOID(tabBarFrameNode);
468 auto tabBarPattern = tabBarFrameNode->GetPattern<TabBarPattern>();
469 CHECK_NULL_VOID(tabBarPattern);
470 tabBarPattern->RemoveTabBarItemInfo(tabBarItemId);
471 tabBarNode->RemoveChild(tabBarItemNode);
472 tabContentNode->ResetTabBarItemId();
473
474 auto tabsNode = FindTabsNode(tabContentNode);
475 CHECK_NULL_VOID(tabsNode);
476 tabsNode->RemoveBuilderByContentId(tabContentNode->GetId());
477 tabBarFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
478 }
479
SetTabBar(const std::optional<std::string> & text,const std::optional<std::string> & icon,const std::optional<TabBarSymbol> & tabBarSymbol,TabBarBuilderFunc && builder,bool)480 void TabContentModelNG::SetTabBar(const std::optional<std::string>& text, const std::optional<std::string>& icon,
481 const std::optional<TabBarSymbol>& tabBarSymbol, TabBarBuilderFunc&& builder, bool /*useContentOnly*/)
482 {
483 ACE_UPDATE_LAYOUT_PROPERTY(TabContentLayoutProperty, Icon, icon.value_or(""));
484 ACE_UPDATE_LAYOUT_PROPERTY(TabContentLayoutProperty, Text, text.value_or(""));
485 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
486 CHECK_NULL_VOID(frameNodePattern);
487 frameNodePattern->SetTabBar(text.value_or(""), icon.value_or(""), tabBarSymbol, std::move(builder));
488 }
489
SetTabBarStyle(TabBarStyle tabBarStyle)490 void TabContentModelNG::SetTabBarStyle(TabBarStyle tabBarStyle)
491 {
492 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
493 CHECK_NULL_VOID(frameNodePattern);
494 frameNodePattern->SetTabBarStyle(tabBarStyle);
495 }
496
SetIndicator(const IndicatorStyle & indicator)497 void TabContentModelNG::SetIndicator(const IndicatorStyle& indicator)
498 {
499 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
500 CHECK_NULL_VOID(frameNodePattern);
501 frameNodePattern->SetIndicatorStyle(indicator);
502 }
503
SetCustomTabBar(FrameNode * node,FrameNode * tabBar)504 void TabContentModelNG::SetCustomTabBar(FrameNode* node, FrameNode* tabBar)
505 {
506 CHECK_NULL_VOID(node);
507 CHECK_NULL_VOID(tabBar);
508 auto frameNodePattern = node->GetPattern<TabContentPattern>();
509 CHECK_NULL_VOID(frameNodePattern);
510 frameNodePattern->SetTabBarStyle(TabBarStyle::NOSTYLE);
511 frameNodePattern->SetCustomTabBar(tabBar);
512 }
513
SetBoard(const BoardStyle & board)514 void TabContentModelNG::SetBoard(const BoardStyle& board)
515 {
516 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
517 CHECK_NULL_VOID(frameNodePattern);
518 frameNodePattern->SetBoardStyle(board);
519 }
520
SetSelectedMode(SelectedMode selectedMode)521 void TabContentModelNG::SetSelectedMode(SelectedMode selectedMode)
522 {
523 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
524 CHECK_NULL_VOID(frameNodePattern);
525 frameNodePattern->SetSelectedMode(selectedMode);
526 }
527
SetLabelStyle(const LabelStyle & labelStyle)528 void TabContentModelNG::SetLabelStyle(const LabelStyle& labelStyle)
529 {
530 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
531 CHECK_NULL_VOID(frameNodePattern);
532 frameNodePattern->SetLabelStyle(labelStyle);
533 }
534
SetIconStyle(const IconStyle & iconStyle)535 void TabContentModelNG::SetIconStyle(const IconStyle& iconStyle)
536 {
537 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
538 CHECK_NULL_VOID(frameNodePattern);
539 frameNodePattern->SetIconStyle(iconStyle);
540 }
541
SetPadding(const PaddingProperty & padding)542 void TabContentModelNG::SetPadding(const PaddingProperty& padding)
543 {
544 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
545 CHECK_NULL_VOID(frameNodePattern);
546 frameNodePattern->SetPadding(padding);
547 }
548
SetUseLocalizedPadding(bool useLocalizedPadding)549 void TabContentModelNG::SetUseLocalizedPadding(bool useLocalizedPadding)
550 {
551 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
552 CHECK_NULL_VOID(frameNodePattern);
553 frameNodePattern->SetUseLocalizedPadding(useLocalizedPadding);
554 }
555
SetLayoutMode(LayoutMode layoutMode)556 void TabContentModelNG::SetLayoutMode(LayoutMode layoutMode)
557 {
558 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
559 CHECK_NULL_VOID(frameNodePattern);
560 frameNodePattern->SetLayoutMode(layoutMode);
561 }
562
SetVerticalAlign(FlexAlign verticalAlign)563 void TabContentModelNG::SetVerticalAlign(FlexAlign verticalAlign)
564 {
565 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
566 CHECK_NULL_VOID(frameNodePattern);
567 frameNodePattern->SetVerticalAlign(verticalAlign);
568 }
569
SetSymmetricExtensible(bool isExtensible)570 void TabContentModelNG::SetSymmetricExtensible(bool isExtensible)
571 {
572 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
573 CHECK_NULL_VOID(frameNodePattern);
574 frameNodePattern->SetSymmetricExtensible(isExtensible);
575 }
576
SetId(const std::string & id)577 void TabContentModelNG::SetId(const std::string& id)
578 {
579 auto frameNodePattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
580 CHECK_NULL_VOID(frameNodePattern);
581 frameNodePattern->SetId(id);
582 }
583
UpdateLabelStyle(const LabelStyle & labelStyle,RefPtr<TextLayoutProperty> textLayoutProperty)584 void TabContentModelNG::UpdateLabelStyle(const LabelStyle& labelStyle, RefPtr<TextLayoutProperty> textLayoutProperty)
585 {
586 CHECK_NULL_VOID(textLayoutProperty);
587
588 if (labelStyle.fontSize.has_value()) {
589 textLayoutProperty->UpdateFontSize(labelStyle.fontSize.value());
590 }
591 if (labelStyle.fontWeight.has_value()) {
592 textLayoutProperty->UpdateFontWeight(labelStyle.fontWeight.value());
593 }
594 if (labelStyle.fontStyle.has_value()) {
595 textLayoutProperty->UpdateItalicFontStyle(labelStyle.fontStyle.value());
596 }
597 if (labelStyle.fontFamily.has_value()) {
598 textLayoutProperty->UpdateFontFamily(labelStyle.fontFamily.value());
599 }
600 if (labelStyle.textOverflow.has_value()) {
601 textLayoutProperty->UpdateTextOverflow(labelStyle.textOverflow.value());
602 }
603 if (labelStyle.maxLines.has_value()) {
604 textLayoutProperty->UpdateMaxLines(labelStyle.maxLines.value());
605 }
606 if (labelStyle.minFontSize.has_value()) {
607 textLayoutProperty->UpdateAdaptMinFontSize(labelStyle.minFontSize.value());
608 }
609 if (labelStyle.maxFontSize.has_value()) {
610 textLayoutProperty->UpdateAdaptMaxFontSize(labelStyle.maxFontSize.value());
611 }
612 if (labelStyle.heightAdaptivePolicy.has_value()) {
613 textLayoutProperty->UpdateHeightAdaptivePolicy(labelStyle.heightAdaptivePolicy.value());
614 }
615 }
616
UpdateDefaultSymbol(RefPtr<TabTheme> & tabTheme,RefPtr<TextLayoutProperty> symbolProperty)617 void TabContentModelNG::UpdateDefaultSymbol(RefPtr<TabTheme>& tabTheme, RefPtr<TextLayoutProperty> symbolProperty)
618 {
619 symbolProperty->UpdateFontSize(tabTheme->GetBottomTabImageSize());
620 symbolProperty->UpdateSymbolRenderingStrategy(DEFAULT_RENDERING_STRATEGY);
621 UpdateSymbolEffect(symbolProperty, false);
622 }
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)623 void TabContentModelNG::UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
624 {
625 auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
626 symbolEffectOptions.SetIsTxtActive(isActive);
627 symbolEffectOptions.SetIsTxtActiveSource(0);
628 symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
629 }
630
SetOnWillShow(std::function<void ()> && onWillShow)631 void TabContentModelNG::SetOnWillShow(std::function<void()>&& onWillShow)
632 {
633 auto tabContentNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
634 CHECK_NULL_VOID(tabContentNode);
635 auto tabContentEventHub = tabContentNode->GetEventHub<TabContentEventHub>();
636 CHECK_NULL_VOID(tabContentEventHub);
637 tabContentEventHub->SetOnWillShow(onWillShow);
638 }
639
SetOnWillHide(std::function<void ()> && onWillHide)640 void TabContentModelNG::SetOnWillHide(std::function<void()>&& onWillHide)
641 {
642 auto tabContentNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
643 CHECK_NULL_VOID(tabContentNode);
644 auto tabContentEventHub = tabContentNode->GetEventHub<TabContentEventHub>();
645 CHECK_NULL_VOID(tabContentEventHub);
646 tabContentEventHub->SetOnWillHide(onWillHide);
647 }
648
SetCustomStyleNode(const RefPtr<FrameNode> & customStyleNode)649 void TabContentModelNG::SetCustomStyleNode(const RefPtr<FrameNode>& customStyleNode)
650 {
651 auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<TabContentPattern>();
652 CHECK_NULL_VOID(pattern);
653 pattern->SetCustomStyleNode(customStyleNode);
654 }
655
SetTabBarBuilder(FrameNode * node,TabBarBuilderFunc && builder)656 void TabContentModelNG::SetTabBarBuilder(FrameNode* node, TabBarBuilderFunc&& builder)
657 {
658 CHECK_NULL_VOID(node);
659 auto frameNodePattern = node->GetPattern<TabContentPattern>();
660 CHECK_NULL_VOID(frameNodePattern);
661 frameNodePattern->SetTabBar("", "", std::nullopt, std::move(builder));
662 }
663
SetTabBarLabel(FrameNode * node,const std::string & label)664 void TabContentModelNG::SetTabBarLabel(FrameNode* node, const std::string& label)
665 {
666 CHECK_NULL_VOID(node);
667 auto frameNodePattern = node->GetPattern<TabContentPattern>();
668 CHECK_NULL_VOID(frameNodePattern);
669 frameNodePattern->SetTabBar(label, "", std::nullopt, nullptr);
670 }
671 } // namespace OHOS::Ace::NG
672