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_node.h"
17
18 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
19 #include "core/components_ng/pattern/tabs/tab_content_model_ng.h"
20 #include "core/components_ng/pattern/tabs/tab_content_pattern.h"
21
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr int DEFAULT_MAXLINES = 1;
25 } // namespace
26
OnAttachToMainTree(bool recursive)27 void TabContentNode::OnAttachToMainTree(bool recursive)
28 {
29 if (!UseOffscreenProcess()) {
30 ProcessTabBarItem();
31 }
32 FrameNode::OnOffscreenProcess(recursive);
33 }
34
OnDetachFromMainTree(bool recursive)35 void TabContentNode::OnDetachFromMainTree(bool recursive)
36 {
37 auto tabs = TabContentModelNG::FindTabsNode(Referenced::Claim(this));
38 CHECK_NULL_VOID(tabs);
39
40 if (!tabs->IsOnMainTree()) {
41 return;
42 }
43
44 // Change focus to the other tab if current is being deleted
45 auto swiper = AceType::DynamicCast<FrameNode>(tabs->GetTabs());
46 CHECK_NULL_VOID(swiper);
47
48 auto swiperPattern = AceType::DynamicCast<SwiperPattern>(swiper->GetPattern());
49 CHECK_NULL_VOID(swiperPattern);
50
51 auto deletedIdx = swiper->GetChildFlatIndex(GetId()).second;
52 auto currentIdx = swiperPattern->GetCurrentShownIndex();
53 // Removing currently shown tab, focus on first after that
54 if (currentIdx == deletedIdx) {
55 swiperPattern->GetSwiperController()->SwipeToWithoutAnimation(0);
56 }
57 TabContentModelNG::RemoveTabBarItem(Referenced::Claim(this));
58
59 // Removing tab before current, re-focus on the same tab with new index
60 if (currentIdx > deletedIdx) {
61 swiperPattern->GetSwiperController()->SwipeToWithoutAnimation(currentIdx - 1);
62 }
63 }
64
OnOffscreenProcess(bool recursive)65 void TabContentNode::OnOffscreenProcess(bool recursive)
66 {
67 ProcessTabBarItem();
68 FrameNode::OnOffscreenProcess(recursive);
69 }
70
ProcessTabBarItem()71 void TabContentNode::ProcessTabBarItem()
72 {
73 auto tabs = TabContentModelNG::FindTabsNode(Referenced::Claim(this));
74 CHECK_NULL_VOID(tabs);
75 auto swiper = tabs->GetTabs();
76 CHECK_NULL_VOID(swiper);
77 auto myIndex = swiper->GetChildFlatIndex(GetId()).second;
78 bool update = false;
79 #ifdef UICAST_COMPONENT_SUPPORTED
80 do {
81 auto container = Container::Current();
82 CHECK_NULL_BREAK(container);
83 auto distributedUI = container->GetDistributedUI();
84 CHECK_NULL_BREAK(distributedUI);
85 if (distributedUI->IsSinkMode()) {
86 update = true;
87 }
88 } while (false);
89 #endif
90 TabContentModelNG::AddTabBarItem(Referenced::Claim(this), myIndex, update);
91 }
92
GetOrCreateTabContentNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)93 RefPtr<TabContentNode> TabContentNode::GetOrCreateTabContentNode(
94 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
95 {
96 auto node = GetFrameNode(tag, nodeId);
97 auto tabContentNode = AceType::DynamicCast<TabContentNode>(node);
98
99 if (tabContentNode) {
100 return tabContentNode;
101 }
102
103 auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
104 tabContentNode = AceType::MakeRefPtr<TabContentNode>(tag, nodeId, pattern, false);
105 tabContentNode->InitializePatternAndContext();
106 ElementRegister::GetInstance()->AddUINode(tabContentNode);
107 return tabContentNode;
108 }
109
ToJsonValue(std::unique_ptr<JsonValue> & json) const110 void TabContentNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
111 {
112 FrameNode::ToJsonValue(json);
113 auto tabBar = JsonUtil::Create(true);
114 auto tabContentPattern = GetPattern<TabContentPattern>();
115 CHECK_NULL_VOID(tabContentPattern);
116
117 auto indicator = JsonUtil::Create(true);
118 auto indicatorStyle = tabContentPattern->GetIndicatorStyle();
119 indicator->Put("color", indicatorStyle.color.ColorToString().c_str());
120 indicator->Put("height", indicatorStyle.height.ToString().c_str());
121 indicator->Put("width", indicatorStyle.width.ToString().c_str());
122 indicator->Put("borderRadius", indicatorStyle.borderRadius.ToString().c_str());
123 indicator->Put("marginTop", indicatorStyle.marginTop.ToString().c_str());
124 tabBar->Put("indicator", indicator);
125
126 auto board = JsonUtil::Create(true);
127 auto boardStyle = tabContentPattern->GetBoardStyle();
128 board->Put("borderRadius", boardStyle.borderRadius.ToString().c_str());
129 tabBar->Put("board", board);
130
131 tabBar->Put("selectedMode", tabContentPattern->GetSelectedMode() == SelectedMode::INDICATOR ?
132 "SelectedMode.INDICATOR" : "SelectedMode.BOARD");
133
134 auto font = JsonUtil::Create(true);
135 auto labelStyle = tabContentPattern->GetLabelStyle();
136 font->Put("size", labelStyle.fontSize.value_or(Dimension(0)).ToString().c_str());
137 font->Put("weight",
138 V2::ConvertWrapFontWeightToStirng(labelStyle.fontWeight.value_or(FontWeight::NORMAL)).c_str());
139 std::vector<std::string> emptyFontFamily = { "" };
140 auto fontFamilyVector = labelStyle.fontFamily.value_or(emptyFontFamily);
141 std::string fontFamily = fontFamilyVector.at(0);
142 for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
143 fontFamily += ',' + fontFamilyVector.at(i);
144 }
145 font->Put("family", fontFamily.c_str());
146 font->Put("style", labelStyle.fontStyle.value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
147 ? "FontStyle.Normal"
148 : "FontStyle.Italic");
149
150 auto label = JsonUtil::Create(true);
151 label->Put("overflow",
152 V2::ConvertWrapTextOverflowToString(labelStyle.textOverflow.value_or(TextOverflow::ELLIPSIS)).c_str());
153 label->Put("maxLines", std::to_string(labelStyle.maxLines.value_or(DEFAULT_MAXLINES)).c_str());
154 label->Put("minFontSize", labelStyle.minFontSize.value_or(Dimension(0)).ToString().c_str());
155 label->Put("maxFontSize", labelStyle.maxFontSize.value_or(Dimension(0)).ToString().c_str());
156 label->Put("heightAdaptivePolicy", V2::ConvertWrapTextHeightAdaptivePolicyToString(
157 labelStyle.heightAdaptivePolicy.value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST)).c_str());
158 label->Put("font", font);
159 tabBar->Put("labelStyle", label);
160
161 tabBar->Put("padding", tabContentPattern->GetPadding().ToJsonString().c_str());
162 tabBar->Put(
163 "verticalAlign", ConvertFlexAlignToString(tabContentPattern->GetBottomTabBarStyle().verticalAlign).c_str());
164 tabBar->Put("layoutMode", ConvertLayoutModeToString(tabContentPattern->GetBottomTabBarStyle().layoutMode).c_str());
165 tabBar->Put(
166 "symmetricExtensible", tabContentPattern->GetBottomTabBarStyle().symmetricExtensible ? "true" : "false");
167 tabBar->Put("id", tabContentPattern->GetId().c_str());
168
169 json->Put("tabBar", tabBar);
170 }
171
ConvertFlexAlignToString(FlexAlign verticalAlign) const172 std::string TabContentNode::ConvertFlexAlignToString(FlexAlign verticalAlign) const
173 {
174 if (verticalAlign == FlexAlign::FLEX_START) {
175 return "VerticalAlign.Top";
176 } else if (verticalAlign == FlexAlign::FLEX_END) {
177 return "VerticalAlign.Bottom";
178 }
179 return "VerticalAlign.Center";
180 }
181
ConvertLayoutModeToString(LayoutMode layoutMode) const182 std::string TabContentNode::ConvertLayoutModeToString(LayoutMode layoutMode) const
183 {
184 if (layoutMode == LayoutMode::VERTICAL) {
185 return "LayoutMode.VERTICAL";
186 } else if (layoutMode == LayoutMode::HORIZONTAL) {
187 return "LayoutMode.HORIZONTAL";
188 }
189 return "LayoutMode.AUTO";
190 }
191 } // namespace OHOS::Ace::NG
192