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/base/inspector_filter.h"
19 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
20 #include "core/components_ng/pattern/tabs/tab_content_model_ng.h"
21 #include "core/components_ng/pattern/tabs/tab_content_pattern.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr int DEFAULT_MAXLINES = 1;
26 } // namespace
27
OnAttachToMainTree(bool recursive)28 void TabContentNode::OnAttachToMainTree(bool recursive)
29 {
30 FrameNode::OnAttachToMainTree(recursive);
31 if (!UseOffscreenProcess()) {
32 ProcessTabBarItem();
33 }
34 FrameNode::OnOffscreenProcess(recursive);
35 }
36
OnDetachFromMainTree(bool recursive,PipelineContext * context)37 void TabContentNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
38 {
39 FrameNode::OnDetachFromMainTree(recursive, context);
40 auto tabs = TabContentModelNG::FindTabsNode(Referenced::Claim(this));
41 CHECK_NULL_VOID(tabs);
42
43 if (!tabs->IsOnMainTree()) {
44 return;
45 }
46
47 TabContentModelNG::RemoveTabBarItem(Referenced::Claim(this));
48 }
49
OnOffscreenProcess(bool recursive)50 void TabContentNode::OnOffscreenProcess(bool recursive)
51 {
52 ProcessTabBarItem();
53 FrameNode::OnOffscreenProcess(recursive);
54 }
55
ProcessTabBarItem()56 void TabContentNode::ProcessTabBarItem()
57 {
58 auto tabs = TabContentModelNG::FindTabsNode(Referenced::Claim(this));
59 CHECK_NULL_VOID(tabs);
60 auto swiper = tabs->GetTabs();
61 CHECK_NULL_VOID(swiper);
62 auto myIndex = swiper->GetChildFlatIndex(GetId()).second;
63 bool update = false;
64 #ifdef UICAST_COMPONENT_SUPPORTED
65 do {
66 auto container = Container::Current();
67 CHECK_NULL_BREAK(container);
68 auto distributedUI = container->GetDistributedUI();
69 CHECK_NULL_BREAK(distributedUI);
70 if (distributedUI->IsSinkMode()) {
71 update = true;
72 }
73 } while (false);
74 #endif
75 TabContentModelNG::AddTabBarItem(Referenced::Claim(this), myIndex, update);
76 }
77
GetOrCreateTabContentNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)78 RefPtr<TabContentNode> TabContentNode::GetOrCreateTabContentNode(
79 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
80 {
81 auto node = GetFrameNode(tag, nodeId);
82 auto tabContentNode = AceType::DynamicCast<TabContentNode>(node);
83
84 if (tabContentNode) {
85 return tabContentNode;
86 }
87
88 auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
89 tabContentNode = AceType::MakeRefPtr<TabContentNode>(tag, nodeId, pattern, false);
90 tabContentNode->InitializePatternAndContext();
91 ElementRegister::GetInstance()->AddUINode(tabContentNode);
92 return tabContentNode;
93 }
94
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const95 void TabContentNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
96 {
97 FrameNode::ToJsonValue(json, filter);
98 /* no fixed attr below, just return */
99 if (filter.IsFastFilter()) {
100 return;
101 }
102 auto tabBar = JsonUtil::Create(true);
103 auto tabContentPattern = GetPattern<TabContentPattern>();
104 CHECK_NULL_VOID(tabContentPattern);
105
106 auto indicator = JsonUtil::Create(true);
107 auto indicatorStyle = tabContentPattern->GetIndicatorStyle();
108 indicator->Put("color", indicatorStyle.color.ColorToString().c_str());
109 indicator->Put("height", indicatorStyle.height.ToString().c_str());
110 indicator->Put("width", indicatorStyle.width.ToString().c_str());
111 indicator->Put("borderRadius", indicatorStyle.borderRadius.ToString().c_str());
112 indicator->Put("marginTop", indicatorStyle.marginTop.ToString().c_str());
113 tabBar->Put("indicator", indicator);
114
115 auto board = JsonUtil::Create(true);
116 auto boardStyle = tabContentPattern->GetBoardStyle();
117 board->Put("borderRadius", boardStyle.borderRadius.ToString().c_str());
118 tabBar->Put("board", board);
119
120 tabBar->Put("selectedMode", tabContentPattern->GetSelectedMode() == SelectedMode::INDICATOR ?
121 "SelectedMode.INDICATOR" : "SelectedMode.BOARD");
122
123 auto font = JsonUtil::Create(true);
124 auto labelStyle = tabContentPattern->GetLabelStyle();
125 font->Put("size", labelStyle.fontSize.value_or(Dimension(0)).ToString().c_str());
126 font->Put("weight",
127 V2::ConvertWrapFontWeightToStirng(labelStyle.fontWeight.value_or(FontWeight::NORMAL)).c_str());
128 std::vector<std::string> emptyFontFamily = { "HarmonyOS Sans" };
129 auto fontFamilyVector = labelStyle.fontFamily.value_or(emptyFontFamily);
130 std::string fontFamily = fontFamilyVector.at(0);
131 for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
132 fontFamily += ',' + fontFamilyVector.at(i);
133 }
134 font->Put("family", fontFamily.c_str());
135 font->Put("style", labelStyle.fontStyle.value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
136 ? "FontStyle.Normal"
137 : "FontStyle.Italic");
138
139 auto label = JsonUtil::Create(true);
140 label->Put("overflow",
141 V2::ConvertWrapTextOverflowToString(labelStyle.textOverflow.value_or(TextOverflow::ELLIPSIS)).c_str());
142 label->Put("maxLines", std::to_string(labelStyle.maxLines.value_or(DEFAULT_MAXLINES)).c_str());
143 label->Put("minFontSize", labelStyle.minFontSize.value_or(Dimension(0)).ToString().c_str());
144 label->Put("maxFontSize", labelStyle.maxFontSize.value_or(Dimension(0)).ToString().c_str());
145 label->Put("heightAdaptivePolicy", V2::ConvertWrapTextHeightAdaptivePolicyToString(
146 labelStyle.heightAdaptivePolicy.value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST)).c_str());
147 label->Put("font", font);
148 auto pipelineContext = PipelineContext::GetCurrentContext();
149 CHECK_NULL_VOID(pipelineContext);
150 auto tabTheme = pipelineContext->GetTheme<TabTheme>();
151 CHECK_NULL_VOID(tabTheme);
152 label->Put("unselectedColor", labelStyle.unselectedColor.value_or(
153 tabTheme->GetSubTabTextOffColor()).ColorToString().c_str());
154 auto selectColor = tabContentPattern->GetSelectedMode() == SelectedMode::BOARD &&
155 GetTabBarAxis() == Axis::HORIZONTAL ? tabTheme->GetSubTabBoardTextOnColor() : tabTheme->GetSubTabTextOnColor();
156 label->Put("selectedColor", labelStyle.selectedColor.value_or(selectColor).ColorToString().c_str());
157 tabBar->Put("labelStyle", label);
158
159 auto iconStyle = tabContentPattern->GetIconStyle();
160 auto icon = JsonUtil::Create(true);
161 icon->Put("unselectedColor", iconStyle.unselectedColor.value_or(
162 tabTheme->GetBottomTabIconOff()).ColorToString().c_str());
163 icon->Put("selectedColor", iconStyle.selectedColor.value_or(
164 tabTheme->GetBottomTabIconOn()).ColorToString().c_str());
165 tabBar->Put("iconStyle", icon);
166
167 tabBar->Put("padding", tabContentPattern->GetPadding().ToJsonString().c_str());
168 tabBar->Put(
169 "verticalAlign", ConvertFlexAlignToString(tabContentPattern->GetBottomTabBarStyle().verticalAlign).c_str());
170 tabBar->Put("layoutMode", ConvertLayoutModeToString(tabContentPattern->GetBottomTabBarStyle().layoutMode).c_str());
171 tabBar->Put(
172 "symmetricExtensible", tabContentPattern->GetBottomTabBarStyle().symmetricExtensible ? "true" : "false");
173 tabBar->Put("id", tabContentPattern->GetId().c_str());
174
175 json->PutExtAttr("tabBar", tabBar, filter);
176 }
177
GetTabBarAxis() const178 Axis TabContentNode::GetTabBarAxis() const
179 {
180 if (!tabBarItemId_.has_value()) {
181 return Axis::HORIZONTAL;
182 }
183 auto columnNode = GetFrameNode(V2::COLUMN_ETS_TAG, tabBarItemId_.value());
184 CHECK_NULL_RETURN(columnNode, Axis::HORIZONTAL);
185 auto tabBarNode = AceType::DynamicCast<FrameNode>(columnNode->GetParent());
186 CHECK_NULL_RETURN(tabBarNode, Axis::HORIZONTAL);
187 auto tabBarLayoutProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
188 CHECK_NULL_RETURN(tabBarLayoutProperty, Axis::HORIZONTAL);
189 return tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
190 }
191
ConvertFlexAlignToString(FlexAlign verticalAlign) const192 std::string TabContentNode::ConvertFlexAlignToString(FlexAlign verticalAlign) const
193 {
194 if (verticalAlign == FlexAlign::FLEX_START) {
195 return "VerticalAlign.Top";
196 } else if (verticalAlign == FlexAlign::FLEX_END) {
197 return "VerticalAlign.Bottom";
198 }
199 return "VerticalAlign.Center";
200 }
201
ConvertLayoutModeToString(LayoutMode layoutMode) const202 std::string TabContentNode::ConvertLayoutModeToString(LayoutMode layoutMode) const
203 {
204 if (layoutMode == LayoutMode::VERTICAL) {
205 return "LayoutMode.VERTICAL";
206 } else if (layoutMode == LayoutMode::HORIZONTAL) {
207 return "LayoutMode.HORIZONTAL";
208 }
209 return "LayoutMode.AUTO";
210 }
211 } // namespace OHOS::Ace::NG
212