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 // Change focus to the other tab if current is being deleted
41 auto swiper = AceType::DynamicCast<FrameNode>(tabs->GetTabs());
42 CHECK_NULL_VOID(swiper);
43
44 auto swiperPattern = AceType::DynamicCast<SwiperPattern>(swiper->GetPattern());
45 CHECK_NULL_VOID(swiperPattern);
46
47 auto deletedIdx = swiper->GetChildFlatIndex(GetId()).second;
48 auto currentIdx = swiperPattern->GetCurrentShownIndex();
49 LOGD("Deleting tab: %{public}d, currentTab: %{public}d", deletedIdx, swiperPattern->GetCurrentShownIndex());
50
51 // Removing currently shown tab, focus on first after that
52 if (currentIdx == deletedIdx) {
53 swiperPattern->GetSwiperController()->SwipeToWithoutAnimation(0);
54 }
55 TabContentModelNG::RemoveTabBarItem(Referenced::Claim(this));
56
57 // Removing tab before current, re-focus on the same tab with new index
58 if (currentIdx > deletedIdx) {
59 LOGD("RE-activate TAB with new IDX %{public}d from idx %{public}d", currentIdx - 1, deletedIdx);
60 swiperPattern->GetSwiperController()->SwipeToWithoutAnimation(currentIdx - 1);
61 }
62 }
63
OnOffscreenProcess(bool recursive)64 void TabContentNode::OnOffscreenProcess(bool recursive)
65 {
66 ProcessTabBarItem();
67 FrameNode::OnOffscreenProcess(recursive);
68 }
69
ProcessTabBarItem()70 void TabContentNode::ProcessTabBarItem()
71 {
72 auto tabs = TabContentModelNG::FindTabsNode(Referenced::Claim(this));
73 CHECK_NULL_VOID(tabs);
74 auto swiper = tabs->GetTabs();
75 CHECK_NULL_VOID(swiper);
76 auto myIndex = swiper->GetChildFlatIndex(GetId()).second;
77 bool update = false;
78 #ifdef UICAST_COMPONENT_SUPPORTED
79 do {
80 auto container = Container::Current();
81 CHECK_NULL_BREAK(container);
82 auto distributedUI = container->GetDistributedUI();
83 CHECK_NULL_BREAK(distributedUI);
84 if (distributedUI->IsSinkMode()) {
85 update = true;
86 }
87 } while (false);
88 #endif
89 TabContentModelNG::AddTabBarItem(Referenced::Claim(this), myIndex, update);
90 }
91
GetOrCreateTabContentNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)92 RefPtr<TabContentNode> TabContentNode::GetOrCreateTabContentNode(
93 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
94 {
95 auto node = GetFrameNode(tag, nodeId);
96 auto tabContentNode = AceType::DynamicCast<TabContentNode>(node);
97
98 if (tabContentNode) {
99 LOGD("found existing");
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
115 auto tabContentPattern = GetPattern<TabContentPattern>();
116 CHECK_NULL_VOID(tabContentPattern);
117
118 auto indicator = JsonUtil::Create(true);
119 auto indicatorStyle = tabContentPattern->GetIndicatorStyle();
120 indicator->Put("color", indicatorStyle.color.ColorToString().c_str());
121 indicator->Put("height", indicatorStyle.height.ToString().c_str());
122 indicator->Put("width", indicatorStyle.width.ToString().c_str());
123 indicator->Put("borderRadius", indicatorStyle.borderRadius.ToString().c_str());
124 indicator->Put("marginTop", indicatorStyle.marginTop.ToString().c_str());
125 tabBar->Put("indicator", indicator);
126
127 auto board = JsonUtil::Create(true);
128 auto boardStyle = tabContentPattern->GetBoardStyle();
129 board->Put("borderRadius", boardStyle.borderRadius.ToString().c_str());
130 tabBar->Put("board", board);
131
132 tabBar->Put("selectedMode", tabContentPattern->GetSelectedMode() == SelectedMode::INDICATOR ?
133 "SelectedMode.INDICATOR" : "SelectedMode.BOARD");
134
135 auto font = JsonUtil::Create(true);
136 auto labelStyle = tabContentPattern->GetLabelStyle();
137 font->Put("size", labelStyle.fontSize.value_or(Dimension(0)).ToString().c_str());
138 font->Put("weight",
139 V2::ConvertWrapFontWeightToStirng(labelStyle.fontWeight.value_or(FontWeight::NORMAL)).c_str());
140 std::vector<std::string> emptyFontFamily = { "" };
141 auto fontFamilyVector = labelStyle.fontFamily.value_or(emptyFontFamily);
142 std::string fontFamily = fontFamilyVector.at(0);
143 for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
144 fontFamily += ',' + fontFamilyVector.at(i);
145 }
146 font->Put("family", fontFamily.c_str());
147 font->Put("style", labelStyle.fontStyle.value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
148 ? "FontStyle.Normal"
149 : "FontStyle.Italic");
150
151 auto label = JsonUtil::Create(true);
152 label->Put("overflow",
153 V2::ConvertWrapTextOverflowToString(labelStyle.textOverflow.value_or(TextOverflow::ELLIPSIS)).c_str());
154 label->Put("maxLines", std::to_string(labelStyle.maxLines.value_or(DEFAULT_MAXLINES)).c_str());
155 label->Put("minFontSize", labelStyle.minFontSize.value_or(Dimension(0)).ToString().c_str());
156 label->Put("maxFontSize", labelStyle.maxFontSize.value_or(Dimension(0)).ToString().c_str());
157 label->Put("heightAdaptivePolicy", V2::ConvertWrapTextHeightAdaptivePolicyToString(
158 labelStyle.heightAdaptivePolicy.value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST)).c_str());
159 label->Put("font", font);
160 tabBar->Put("labelStyle", label);
161
162 tabBar->Put("padding", tabContentPattern->GetPadding().ToJsonString().c_str());
163 tabBar->Put(
164 "verticalAlign", ConvertFlexAlignToString(tabContentPattern->GetBottomTabBarStyle().verticalAlign).c_str());
165 tabBar->Put("layoutMode", ConvertLayoutModeToString(tabContentPattern->GetBottomTabBarStyle().layoutMode).c_str());
166 tabBar->Put(
167 "symmetricExtensible", tabContentPattern->GetBottomTabBarStyle().symmetricExtensible ? "true" : "false");
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