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/tabs_node.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components/common/layout/constants.h"
20 #include "core/components_ng/base/inspector_filter.h"
21 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
22 #include "core/components_ng/pattern/swiper/swiper_paint_property.h"
23 #include "core/components_ng/pattern/tabs/tab_bar_layout_algorithm.h"
24 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
25 #include "core/components_ng/pattern/tabs/tabs_pattern.h"
26 #include "core/components_v2/inspector/inspector_constants.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28
29 namespace OHOS::Ace::NG {
30 namespace {
31
32 const std::string BAR_BLURSTYLE[] = {
33 "BlurStyle.NONE",
34 "BlurStyle.Thin",
35 "BlurStyle.Regular",
36 "BlurStyle.Thick",
37 "BlurStyle.BACKGROUND_THIN",
38 "BlurStyle.BACKGROUND_REGULAR",
39 "BlurStyle.BACKGROUND_THICK",
40 "BlurStyle.BACKGROUND_ULTRA_THICK",
41 "BlurStyle.COMPONENT_ULTRA_THIN",
42 "BlurStyle.COMPONENT_THIN",
43 "BlurStyle.COMPONENT_REGULAR",
44 "BlurStyle.COMPONENT_THICK",
45 "BlurStyle.COMPONENT_ULTRA_THICK"
46 };
47
48 } // namespace
49
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)50 void TabsNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
51 {
52 if (swiperChildren_.find(child->GetId()) != swiperChildren_.end()) {
53 return;
54 }
55
56 swiperChildren_.emplace(child->GetId());
57 auto swiperNode = GetTabs();
58 if (swiperNode) {
59 child->MountToParent(swiperNode);
60 }
61 }
62
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const63 void TabsNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
64 {
65 FrameNode::ToJsonValue(json, filter);
66 json->PutFixedAttr("scrollable", Scrollable(), filter, FIXED_ATTR_SCROLLABLE);
67 /* no fixed attr below, just return */
68 if (filter.IsFastFilter()) {
69 return;
70 }
71 json->PutExtAttr("index", std::to_string(GetIndex()).c_str(), filter);
72 json->PutExtAttr("animationDuration", GetAnimationDuration(), filter);
73 if (GetTabBarMode() == TabBarMode::SCROLLABLE) {
74 auto optionsJson = JsonUtil::Create(true);
75 auto options = GetScrollableBarModeOptions();
76 optionsJson->Put("margin", options.margin.ToString().c_str());
77 if (options.nonScrollableLayoutStyle.value_or(LayoutStyle::ALWAYS_CENTER) == LayoutStyle::ALWAYS_CENTER) {
78 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.ALWAYS_CENTER");
79 } else if (options.nonScrollableLayoutStyle.value() == LayoutStyle::ALWAYS_AVERAGE_SPLIT) {
80 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.ALWAYS_AVERAGE_SPLIT");
81 } else if (options.nonScrollableLayoutStyle.value() == LayoutStyle::SPACE_BETWEEN_OR_CENTER) {
82 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.SPACE_BETWEEN_OR_CENTER");
83 }
84 std::string barMode = "BarMode.Scrollable," + optionsJson->ToString();
85 json->PutExtAttr("barMode", barMode.c_str(), filter);
86 } else {
87 json->PutExtAttr("barMode", "BarMode.Fixed", filter);
88 }
89 json->PutExtAttr("barWidth", std::to_string(GetBarWidth().Value()).c_str(), filter);
90 json->PutExtAttr("barHeight",
91 GetBarAdaptiveHeight() ? "auto" : std::to_string(GetBarHeight().Value()).c_str(), filter);
92 json->PutExtAttr("fadingEdge", GetFadingEdge() ? "true" : "false", filter);
93 json->PutExtAttr("barBackgroundColor", GetBarBackgroundColor().ColorToString().c_str(), filter);
94 json->PutExtAttr("barBackgroundBlurStyle",
95 BAR_BLURSTYLE[static_cast<int32_t>(GetBarBackgroundBlurStyle())].c_str(), filter);
96 json->PutExtAttr("barBackgroundBlurStyleOptions", GetBarBackgroundBlurStyleOptions(), filter);
97 json->PutExtAttr("animationMode", GetAnimationMode().c_str(), filter);
98 json->PutExtAttr("edgeEffect", GetEdgeEffect().c_str(), filter);
99 json->PutExtAttr("barBackgroundEffect", GetBarBackgroundEffect(), filter);
100
101 auto barGridAlignJson = JsonUtil::Create(true);
102 auto barGridAlign = GetBarGridAlign();
103 barGridAlignJson->Put("gutter", barGridAlign.gutter.ToString().c_str());
104 barGridAlignJson->Put("margin", barGridAlign.margin.ToString().c_str());
105 barGridAlignJson->Put("sm", std::to_string(barGridAlign.sm).c_str());
106 barGridAlignJson->Put("md", std::to_string(barGridAlign.md).c_str());
107 barGridAlignJson->Put("lg", std::to_string(barGridAlign.lg).c_str());
108
109 json->PutExtAttr("barGridAlign", barGridAlignJson, filter);
110 }
111
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const112 void TabsNode::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
113 {
114 FrameNode::ToTreeJson(json, config);
115 if (config.contentOnly) {
116 return;
117 }
118 json->Put(TreeKey::SCROLLABLE, Scrollable());
119 }
120
Scrollable() const121 bool TabsNode::Scrollable() const
122 {
123 if (!swiperId_.has_value()) {
124 return true;
125 }
126 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
127 CHECK_NULL_RETURN(swiperNode, true);
128 auto props = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
129 CHECK_NULL_RETURN(props, true);
130 return !props->GetDisableSwipe().value_or(false);
131 }
132
GetAnimationDuration() const133 int32_t TabsNode::GetAnimationDuration() const
134 {
135 int32_t duration = 0;
136 if (!tabBarId_.has_value()) {
137 return duration;
138 }
139 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
140 CHECK_NULL_RETURN(tabBarNode, duration);
141 auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
142 CHECK_NULL_RETURN(tabBarPattern, duration);
143 tabBarPattern->UpdateAnimationDuration();
144 return tabBarPattern->GetAnimationDuration().value_or(duration);
145 }
146
GetIndex() const147 int32_t TabsNode::GetIndex() const
148 {
149 if (!swiperId_.has_value()) {
150 return 0;
151 }
152 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
153 CHECK_NULL_RETURN(swiperNode, 0);
154 auto layoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
155 CHECK_NULL_RETURN(layoutProperty, 0);
156 return layoutProperty->GetIndex().value_or(0);
157 }
158
GetTabBarMode() const159 TabBarMode TabsNode::GetTabBarMode() const
160 {
161 if (!tabBarId_.has_value()) {
162 return TabBarMode::FIXED;
163 }
164 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
165 CHECK_NULL_RETURN(tabBarNode, TabBarMode::FIXED);
166 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
167 CHECK_NULL_RETURN(tabBarProperty, TabBarMode::FIXED);
168 return tabBarProperty->GetTabBarMode().value_or(TabBarMode::FIXED);
169 }
170
GetBarWidth() const171 Dimension TabsNode::GetBarWidth() const
172 {
173 if (!tabBarId_.has_value()) {
174 return 0.0_vp;
175 }
176 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
177 CHECK_NULL_RETURN(tabBarNode, 0.0_vp);
178 auto geometryNode = tabBarNode->GetGeometryNode();
179 CHECK_NULL_RETURN(geometryNode, 0.0_vp);
180 auto frameSize = geometryNode->GetFrameSize();
181 return Dimension(PipelineBase::Px2VpWithCurrentDensity(frameSize.Width()), DimensionUnit::VP);
182 }
183
GetBarAdaptiveHeight() const184 bool TabsNode::GetBarAdaptiveHeight() const
185 {
186 if (!tabBarId_.has_value()) {
187 return false;
188 }
189 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
190 CHECK_NULL_RETURN(tabBarNode, false);
191 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
192 CHECK_NULL_RETURN(tabBarProperty, false);
193 return tabBarProperty->GetBarAdaptiveHeight().value_or(false);
194 }
195
GetBarHeight() const196 Dimension TabsNode::GetBarHeight() const
197 {
198 if (!tabBarId_.has_value()) {
199 return 0.0_vp;
200 }
201 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
202 CHECK_NULL_RETURN(tabBarNode, 0.0_vp);
203 auto geometryNode = tabBarNode->GetGeometryNode();
204 CHECK_NULL_RETURN(geometryNode, 0.0_vp);
205 auto frameSize = geometryNode->GetFrameSize();
206 return Dimension(PipelineBase::Px2VpWithCurrentDensity(frameSize.Height()), DimensionUnit::VP);
207 }
208
GetBarBackgroundColor() const209 Color TabsNode::GetBarBackgroundColor() const
210 {
211 auto backgroundColor = Color::BLACK.BlendOpacity(0.0f);
212 if (!tabBarId_.has_value()) {
213 return backgroundColor;
214 }
215 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
216 CHECK_NULL_RETURN(tabBarNode, backgroundColor);
217 auto tabBarRenderContext = tabBarNode->GetRenderContext();
218 CHECK_NULL_RETURN(tabBarRenderContext, backgroundColor);
219 return tabBarRenderContext->GetBackgroundColor().value_or(backgroundColor);
220 }
221
GetBarBackgroundBlurStyle() const222 BlurStyle TabsNode::GetBarBackgroundBlurStyle() const
223 {
224 auto barBackgroundBlurStyle = BlurStyle::NO_MATERIAL;
225 if (!tabBarId_.has_value()) {
226 return barBackgroundBlurStyle;
227 }
228 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
229 CHECK_NULL_RETURN(tabBarNode, barBackgroundBlurStyle);
230 auto tabBarRenderContext = tabBarNode->GetRenderContext();
231 CHECK_NULL_RETURN(tabBarRenderContext, barBackgroundBlurStyle);
232 auto styleOption = tabBarRenderContext->GetBackBlurStyle().value_or(BlurStyleOption{});
233 return styleOption.blurStyle;
234 }
235
GetBarBackgroundBlurStyleOptions() const236 std::unique_ptr<JsonValue> TabsNode::GetBarBackgroundBlurStyleOptions() const
237 {
238 auto jsonBlurStyle = JsonUtil::Create(true);
239 if (!tabBarId_.has_value()) {
240 return jsonBlurStyle;
241 }
242 static const char* COLOR_MODE[] = { "ThemeColorMode.System", "ThemeColorMode.Light", "ThemeColorMode.Dark" };
243 static const char* ADAPTIVE_COLOR[] = { "AdaptiveColor.Default", "AdaptiveColor.Average" };
244 static const char* POLICY[] = { "BlurStyleActivePolicy.FOLLOWS_WINDOW_ACTIVE_STATE",
245 "BlurStyleActivePolicy.ALWAYS_ACTIVE", "BlurStyleActivePolicy.ALWAYS_INACTIVE" };
246 static const char* BLUR_TYPE[] = { "BlurType.WITHIN_WINDOW", "BlurType.BEHIND_WINDOW" };
247 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
248 CHECK_NULL_RETURN(tabBarNode, jsonBlurStyle);
249 auto tabBarRenderContext = tabBarNode->GetRenderContext();
250 CHECK_NULL_RETURN(tabBarRenderContext, jsonBlurStyle);
251 auto styleOption = tabBarRenderContext->GetBackBlurStyle().value_or(BlurStyleOption{});
252 jsonBlurStyle->Put("colorMode", COLOR_MODE[static_cast<int>(styleOption.colorMode)]);
253 jsonBlurStyle->Put("adaptiveColor",
254 ADAPTIVE_COLOR[static_cast<int>(styleOption.adaptiveColor)]);
255 jsonBlurStyle->Put("policy", POLICY[static_cast<int>(styleOption.policy)]);
256 jsonBlurStyle->Put("type", BLUR_TYPE[static_cast<int>(styleOption.blurType)]);
257 jsonBlurStyle->Put("inactiveColor", styleOption.inactiveColor.ColorToString().c_str());
258 jsonBlurStyle->Put("scale", styleOption.scale);
259 return jsonBlurStyle;
260 }
261
GetFadingEdge() const262 bool TabsNode::GetFadingEdge() const
263 {
264 if (!tabBarId_.has_value()) {
265 return true;
266 }
267 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
268 CHECK_NULL_RETURN(tabBarNode, true);
269 auto tabBarProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
270 CHECK_NULL_RETURN(tabBarProperty, true);
271 return tabBarProperty->GetFadingEdge().value_or(true);
272 }
273
GetBarGridAlign() const274 BarGridColumnOptions TabsNode::GetBarGridAlign() const
275 {
276 BarGridColumnOptions option;
277 if (!tabBarId_.has_value()) {
278 return option;
279 }
280 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
281 CHECK_NULL_RETURN(tabBarNode, option);
282 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
283 CHECK_NULL_RETURN(tabBarProperty, option);
284 return tabBarProperty->GetBarGridAlign().value_or(option);
285 }
286
GetScrollableBarModeOptions() const287 ScrollableBarModeOptions TabsNode::GetScrollableBarModeOptions() const
288 {
289 ScrollableBarModeOptions option;
290 if (!tabBarId_.has_value()) {
291 return option;
292 }
293 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
294 CHECK_NULL_RETURN(tabBarNode, option);
295 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
296 CHECK_NULL_RETURN(tabBarProperty, option);
297 return tabBarProperty->GetScrollableBarModeOptions().value_or(option);
298 }
299
GetAnimationMode() const300 std::string TabsNode::GetAnimationMode() const
301 {
302 std::string ret = "AnimationMode.CONTENT_FIRST";
303 auto tabsPattern = GetPattern<TabsPattern>();
304 CHECK_NULL_RETURN(tabsPattern, ret);
305 TabAnimateMode mode = tabsPattern->GetAnimateMode();
306 switch (mode) {
307 case TabAnimateMode::CONTENT_FIRST:
308 ret = "AnimationMode.CONTENT_FIRST";
309 break;
310 case TabAnimateMode::ACTION_FIRST:
311 ret = "AnimationMode.ACTION_FIRST";
312 break;
313 case TabAnimateMode::NO_ANIMATION:
314 ret = "AnimationMode.NO_ANIMATION";
315 break;
316 case TabAnimateMode::CONTENT_FIRST_WITH_JUMP:
317 ret = "AnimationMode.CONTENT_FIRST_WITH_JUMP";
318 break;
319 case TabAnimateMode::ACTION_FIRST_WITH_JUMP:
320 ret = "AnimationMode.ACTION_FIRST_WITH_JUMP";
321 break;
322 default:
323 ret = "AnimationMode.CONTENT_FIRST";
324 break;
325 }
326 return ret;
327 }
328
GetEdgeEffect() const329 std::string TabsNode::GetEdgeEffect() const
330 {
331 std::string ret = "EdgeEffect::SPRING";
332 if (!swiperId_.has_value()) {
333 return ret;
334 }
335 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
336 CHECK_NULL_RETURN(swiperNode, ret);
337 auto paintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
338 CHECK_NULL_RETURN(paintProperty, ret);
339 EdgeEffect edgeEffect = paintProperty->GetEdgeEffect().value();
340 switch (edgeEffect) {
341 case EdgeEffect::SPRING:
342 ret = "EdgeEffect::SPRING";
343 break;
344 case EdgeEffect::FADE:
345 ret = "EdgeEffect::FADE";
346 break;
347 case EdgeEffect::NONE:
348 ret = "EdgeEffect::NONE";
349 break;
350 default:
351 ret = "EdgeEffect::SPRING";
352 break;
353 }
354 return ret;
355 }
356
GetBarBackgroundEffect() const357 std::unique_ptr<JsonValue> TabsNode::GetBarBackgroundEffect() const
358 {
359 auto jsonEffect = JsonUtil::Create(true);
360 if (!tabBarId_.has_value()) {
361 return jsonEffect;
362 }
363 static const char* ADAPTIVE_COLOR[] = { "AdaptiveColor.Default", "AdaptiveColor.Average" };
364 static const char* POLICY[] = { "BlurStyleActivePolicy.FOLLOWS_WINDOW_ACTIVE_STATE",
365 "BlurStyleActivePolicy.ALWAYS_ACTIVE", "BlurStyleActivePolicy.ALWAYS_INACTIVE" };
366 static const char* BLUR_TYPE[] = { "WITHIN_WINDOW", "BEHIND_WINDOW" };
367 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
368 CHECK_NULL_RETURN(tabBarNode, jsonEffect);
369 auto tabBarRenderContext = tabBarNode->GetRenderContext();
370 CHECK_NULL_RETURN(tabBarRenderContext, jsonEffect);
371 EffectOption effectOption = tabBarRenderContext->GetBackgroundEffect().value_or(effectOption);
372 jsonEffect->Put("radius", effectOption.radius.Value());
373 jsonEffect->Put("saturation", effectOption.saturation);
374 jsonEffect->Put("brightness", effectOption.brightness);
375 jsonEffect->Put("color", effectOption.color.ColorToString().c_str());
376 jsonEffect->Put("adaptiveColor", ADAPTIVE_COLOR[static_cast<int32_t>(effectOption.adaptiveColor)]);
377 jsonEffect->Put("policy", POLICY[static_cast<int>(effectOption.policy)]);
378 jsonEffect->Put("type", BLUR_TYPE[static_cast<int>(effectOption.blurType)]);
379 jsonEffect->Put("inactiveColor", effectOption.inactiveColor.ColorToString().c_str());
380 auto grayscale = "[0,0]";
381 if (effectOption.blurOption.grayscale.size() > 1) {
382 grayscale = ("[" + std::to_string(effectOption.blurOption.grayscale[0]) + "," +
383 std::to_string(effectOption.blurOption.grayscale[1]) + "]").c_str();
384 }
385 jsonEffect->Put("blurOption", grayscale);
386 return jsonEffect;
387 }
388 } // namespace OHOS::Ace::NG
389