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