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("animationCurve", GetAnimationCurveStr(TabBarPhysicalCurve).c_str(), filter);
73 json->PutExtAttr("animationDuration", GetAnimationDuration(), filter);
74 if (GetTabBarMode() == TabBarMode::SCROLLABLE) {
75 auto optionsJson = JsonUtil::Create(true);
76 auto options = GetScrollableBarModeOptions();
77 optionsJson->Put("margin", options.margin.ToString().c_str());
78 if (options.nonScrollableLayoutStyle.value_or(LayoutStyle::ALWAYS_CENTER) == LayoutStyle::ALWAYS_CENTER) {
79 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.ALWAYS_CENTER");
80 } else if (options.nonScrollableLayoutStyle.value() == LayoutStyle::ALWAYS_AVERAGE_SPLIT) {
81 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.ALWAYS_AVERAGE_SPLIT");
82 } else if (options.nonScrollableLayoutStyle.value() == LayoutStyle::SPACE_BETWEEN_OR_CENTER) {
83 optionsJson->Put("nonScrollableLayoutStyle", "LayoutStyle.SPACE_BETWEEN_OR_CENTER");
84 }
85 std::string barMode = "BarMode.Scrollable," + optionsJson->ToString();
86 json->PutExtAttr("barMode", barMode.c_str(), filter);
87 } else {
88 json->PutExtAttr("barMode", "BarMode.Fixed", filter);
89 }
90 json->PutExtAttr("barWidth", std::to_string(GetBarWidth().Value()).c_str(), filter);
91 json->PutExtAttr("barHeight",
92 GetBarAdaptiveHeight() ? "auto" : std::to_string(GetBarHeight().Value()).c_str(), filter);
93 json->PutExtAttr("fadingEdge", GetFadingEdge() ? "true" : "false", filter);
94 json->PutExtAttr("barBackgroundColor", GetBarBackgroundColor().ColorToString().c_str(), filter);
95 json->PutExtAttr("barBackgroundBlurStyle",
96 BAR_BLURSTYLE[static_cast<int32_t>(GetBarBackgroundBlurStyle())].c_str(), filter);
97 json->PutExtAttr("barBackgroundBlurStyleOptions", GetBarBackgroundBlurStyleOptions(), filter);
98 json->PutExtAttr("animationMode", GetAnimationMode().c_str(), filter);
99 json->PutExtAttr("edgeEffect", GetEdgeEffect().c_str(), filter);
100 json->PutExtAttr("barBackgroundEffect", GetBarBackgroundEffect(), filter);
101
102 auto barGridAlignJson = JsonUtil::Create(true);
103 auto barGridAlign = GetBarGridAlign();
104 barGridAlignJson->Put("gutter", barGridAlign.gutter.ToString().c_str());
105 barGridAlignJson->Put("margin", barGridAlign.margin.ToString().c_str());
106 barGridAlignJson->Put("sm", std::to_string(barGridAlign.sm).c_str());
107 barGridAlignJson->Put("md", std::to_string(barGridAlign.md).c_str());
108 barGridAlignJson->Put("lg", std::to_string(barGridAlign.lg).c_str());
109
110 json->PutExtAttr("barGridAlign", barGridAlignJson, filter);
111 }
112
Scrollable() const113 bool TabsNode::Scrollable() const
114 {
115 if (!swiperId_.has_value()) {
116 return true;
117 }
118 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
119 CHECK_NULL_RETURN(swiperNode, true);
120 auto props = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
121 CHECK_NULL_RETURN(props, true);
122 return !props->GetDisableSwipe().value_or(false);
123 }
124
GetAnimationCurve(const RefPtr<Curve> & defaultCurve) const125 const RefPtr<Curve> TabsNode::GetAnimationCurve(const RefPtr<Curve>& defaultCurve) const
126 {
127 if (!swiperId_.has_value()) {
128 return defaultCurve;
129 }
130 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
131 CHECK_NULL_RETURN(swiperNode, defaultCurve);
132 auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
133 CHECK_NULL_RETURN(swiperPaintProperty, defaultCurve);
134 auto curve = swiperPaintProperty->GetCurve().value_or(nullptr);
135 CHECK_NULL_RETURN(curve, defaultCurve);
136 return curve;
137 }
138
GetAnimationCurveStr(const RefPtr<Curve> & defaultCurve) const139 std::string TabsNode::GetAnimationCurveStr(const RefPtr<Curve>& defaultCurve) const
140 {
141 auto curve = GetAnimationCurve(defaultCurve);
142 return curve ? curve->ToString() : "null";
143 }
144
GetAnimationDuration() const145 int32_t TabsNode::GetAnimationDuration() const
146 {
147 int32_t duration = 0;
148 if (!tabBarId_.has_value()) {
149 return duration;
150 }
151 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
152 CHECK_NULL_RETURN(tabBarNode, duration);
153 auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
154 CHECK_NULL_RETURN(tabBarPattern, duration);
155 tabBarPattern->UpdateAnimationDuration();
156 return tabBarPattern->GetAnimationDuration().value_or(duration);
157 }
158
GetIndex() const159 int32_t TabsNode::GetIndex() const
160 {
161 if (!swiperId_.has_value()) {
162 return 0;
163 }
164 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
165 CHECK_NULL_RETURN(swiperNode, 0);
166 auto layoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
167 CHECK_NULL_RETURN(layoutProperty, 0);
168 return layoutProperty->GetIndex().value_or(0);
169 }
170
GetTabBarMode() const171 TabBarMode TabsNode::GetTabBarMode() const
172 {
173 if (!tabBarId_.has_value()) {
174 return TabBarMode::FIXED;
175 }
176 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
177 CHECK_NULL_RETURN(tabBarNode, TabBarMode::FIXED);
178 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
179 CHECK_NULL_RETURN(tabBarProperty, TabBarMode::FIXED);
180 return tabBarProperty->GetTabBarMode().value_or(TabBarMode::FIXED);
181 }
182
GetBarWidth() const183 Dimension TabsNode::GetBarWidth() const
184 {
185 if (!tabBarId_.has_value()) {
186 return 0.0_vp;
187 }
188 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
189 CHECK_NULL_RETURN(tabBarNode, 0.0_vp);
190 auto geometryNode = tabBarNode->GetGeometryNode();
191 CHECK_NULL_RETURN(geometryNode, 0.0_vp);
192 auto frameSize = geometryNode->GetFrameSize();
193 return Dimension(PipelineBase::Px2VpWithCurrentDensity(frameSize.Width()), DimensionUnit::VP);
194 }
195
GetBarAdaptiveHeight() const196 bool TabsNode::GetBarAdaptiveHeight() const
197 {
198 if (!tabBarId_.has_value()) {
199 return false;
200 }
201 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
202 CHECK_NULL_RETURN(tabBarNode, false);
203 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
204 CHECK_NULL_RETURN(tabBarProperty, false);
205 return tabBarProperty->GetBarAdaptiveHeight().value_or(false);
206 }
207
GetBarHeight() const208 Dimension TabsNode::GetBarHeight() const
209 {
210 if (!tabBarId_.has_value()) {
211 return 0.0_vp;
212 }
213 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
214 CHECK_NULL_RETURN(tabBarNode, 0.0_vp);
215 auto geometryNode = tabBarNode->GetGeometryNode();
216 CHECK_NULL_RETURN(geometryNode, 0.0_vp);
217 auto frameSize = geometryNode->GetFrameSize();
218 return Dimension(PipelineBase::Px2VpWithCurrentDensity(frameSize.Height()), DimensionUnit::VP);
219 }
220
GetBarBackgroundColor() const221 Color TabsNode::GetBarBackgroundColor() const
222 {
223 auto backgroundColor = Color::BLACK.BlendOpacity(0.0f);
224 if (!tabBarId_.has_value()) {
225 return backgroundColor;
226 }
227 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
228 CHECK_NULL_RETURN(tabBarNode, backgroundColor);
229 auto tabBarRenderContext = tabBarNode->GetRenderContext();
230 CHECK_NULL_RETURN(tabBarRenderContext, backgroundColor);
231 return tabBarRenderContext->GetBackgroundColor().value_or(backgroundColor);
232 }
233
GetBarBackgroundBlurStyle() const234 BlurStyle TabsNode::GetBarBackgroundBlurStyle() const
235 {
236 auto barBackgroundBlurStyle = BlurStyle::NO_MATERIAL;
237 if (!tabBarId_.has_value()) {
238 return barBackgroundBlurStyle;
239 }
240 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
241 CHECK_NULL_RETURN(tabBarNode, barBackgroundBlurStyle);
242 auto tabBarRenderContext = tabBarNode->GetRenderContext();
243 CHECK_NULL_RETURN(tabBarRenderContext, barBackgroundBlurStyle);
244 auto styleOption = tabBarRenderContext->GetBackBlurStyle().value_or(BlurStyleOption{});
245 return styleOption.blurStyle;
246 }
247
GetBarBackgroundBlurStyleOptions() const248 std::unique_ptr<JsonValue> TabsNode::GetBarBackgroundBlurStyleOptions() const
249 {
250 auto jsonBlurStyle = JsonUtil::Create(true);
251 if (!tabBarId_.has_value()) {
252 return jsonBlurStyle;
253 }
254 static const char* COLOR_MODE[] = { "ThemeColorMode.System", "ThemeColorMode.Light", "ThemeColorMode.Dark" };
255 static const char* ADAPTIVE_COLOR[] = { "AdaptiveColor.Default", "AdaptiveColor.Average" };
256 static const char* POLICY[] = { "BlurStyleActivePolicy.FOLLOWS_WINDOW_ACTIVE_STATE",
257 "BlurStyleActivePolicy.ALWAYS_ACTIVE", "BlurStyleActivePolicy.ALWAYS_INACTIVE" };
258 static const char* BLUR_TYPE[] = { "BlurType.WITHIN_WINDOW", "BlurType.BEHIND_WINDOW" };
259 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
260 CHECK_NULL_RETURN(tabBarNode, jsonBlurStyle);
261 auto tabBarRenderContext = tabBarNode->GetRenderContext();
262 CHECK_NULL_RETURN(tabBarRenderContext, jsonBlurStyle);
263 auto styleOption = tabBarRenderContext->GetBackBlurStyle().value_or(BlurStyleOption{});
264 jsonBlurStyle->Put("colorMode", COLOR_MODE[static_cast<int>(styleOption.colorMode)]);
265 jsonBlurStyle->Put("adaptiveColor",
266 ADAPTIVE_COLOR[static_cast<int>(styleOption.adaptiveColor)]);
267 jsonBlurStyle->Put("policy", POLICY[static_cast<int>(styleOption.policy)]);
268 jsonBlurStyle->Put("type", BLUR_TYPE[static_cast<int>(styleOption.blurType)]);
269 jsonBlurStyle->Put("inactiveColor", styleOption.inactiveColor.ColorToString().c_str());
270 jsonBlurStyle->Put("scale", styleOption.scale);
271 return jsonBlurStyle;
272 }
273
GetFadingEdge() const274 bool TabsNode::GetFadingEdge() const
275 {
276 if (!tabBarId_.has_value()) {
277 return true;
278 }
279 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
280 CHECK_NULL_RETURN(tabBarNode, true);
281 auto tabBarProperty = tabBarNode->GetPaintProperty<TabBarPaintProperty>();
282 CHECK_NULL_RETURN(tabBarProperty, true);
283 return tabBarProperty->GetFadingEdge().value_or(true);
284 }
285
GetBarGridAlign() const286 BarGridColumnOptions TabsNode::GetBarGridAlign() const
287 {
288 BarGridColumnOptions option;
289 if (!tabBarId_.has_value()) {
290 return option;
291 }
292 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
293 CHECK_NULL_RETURN(tabBarNode, option);
294 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
295 CHECK_NULL_RETURN(tabBarProperty, option);
296 return tabBarProperty->GetBarGridAlign().value_or(option);
297 }
298
GetScrollableBarModeOptions() const299 ScrollableBarModeOptions TabsNode::GetScrollableBarModeOptions() const
300 {
301 ScrollableBarModeOptions option;
302 if (!tabBarId_.has_value()) {
303 return option;
304 }
305 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
306 CHECK_NULL_RETURN(tabBarNode, option);
307 auto tabBarProperty = tabBarNode->GetLayoutProperty<TabBarLayoutProperty>();
308 CHECK_NULL_RETURN(tabBarProperty, option);
309 return tabBarProperty->GetScrollableBarModeOptions().value_or(option);
310 }
311
GetAnimationMode() const312 std::string TabsNode::GetAnimationMode() const
313 {
314 std::string ret = "AnimationMode.CONTENT_FIRST";
315 auto tabsPattern = GetPattern<TabsPattern>();
316 CHECK_NULL_RETURN(tabsPattern, ret);
317 TabAnimateMode mode = tabsPattern->GetAnimateMode();
318 switch (mode) {
319 case TabAnimateMode::CONTENT_FIRST:
320 ret = "AnimationMode.CONTENT_FIRST";
321 break;
322 case TabAnimateMode::ACTION_FIRST:
323 ret = "AnimationMode.ACTION_FIRST";
324 break;
325 case TabAnimateMode::NO_ANIMATION:
326 ret = "AnimationMode.NO_ANIMATION";
327 break;
328 case TabAnimateMode::CONTENT_FIRST_WITH_JUMP:
329 ret = "AnimationMode.CONTENT_FIRST_WITH_JUMP";
330 break;
331 case TabAnimateMode::ACTION_FIRST_WITH_JUMP:
332 ret = "AnimationMode.ACTION_FIRST_WITH_JUMP";
333 break;
334 default:
335 ret = "AnimationMode.CONTENT_FIRST";
336 break;
337 }
338 return ret;
339 }
340
GetEdgeEffect() const341 std::string TabsNode::GetEdgeEffect() const
342 {
343 std::string ret = "EdgeEffect::SPRING";
344 if (!swiperId_.has_value()) {
345 return ret;
346 }
347 auto swiperNode = GetFrameNode(V2::SWIPER_ETS_TAG, swiperId_.value());
348 CHECK_NULL_RETURN(swiperNode, ret);
349 auto paintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
350 CHECK_NULL_RETURN(paintProperty, ret);
351 EdgeEffect edgeEffect = paintProperty->GetEdgeEffect().value();
352 switch (edgeEffect) {
353 case EdgeEffect::SPRING:
354 ret = "EdgeEffect::SPRING";
355 break;
356 case EdgeEffect::FADE:
357 ret = "EdgeEffect::FADE";
358 break;
359 case EdgeEffect::NONE:
360 ret = "EdgeEffect::NONE";
361 break;
362 default:
363 ret = "EdgeEffect::SPRING";
364 break;
365 }
366 return ret;
367 }
368
GetBarBackgroundEffect() const369 std::unique_ptr<JsonValue> TabsNode::GetBarBackgroundEffect() const
370 {
371 auto jsonEffect = JsonUtil::Create(true);
372 if (!tabBarId_.has_value()) {
373 return jsonEffect;
374 }
375 static const char* ADAPTIVE_COLOR[] = { "AdaptiveColor.Default", "AdaptiveColor.Average" };
376 static const char* POLICY[] = { "BlurStyleActivePolicy.FOLLOWS_WINDOW_ACTIVE_STATE",
377 "BlurStyleActivePolicy.ALWAYS_ACTIVE", "BlurStyleActivePolicy.ALWAYS_INACTIVE" };
378 static const char* BLUR_TYPE[] = { "WITHIN_WINDOW", "BEHIND_WINDOW" };
379 auto tabBarNode = GetFrameNode(V2::TAB_BAR_ETS_TAG, tabBarId_.value());
380 CHECK_NULL_RETURN(tabBarNode, jsonEffect);
381 auto tabBarRenderContext = tabBarNode->GetRenderContext();
382 CHECK_NULL_RETURN(tabBarRenderContext, jsonEffect);
383 EffectOption effectOption = tabBarRenderContext->GetBackgroundEffect().value_or(effectOption);
384 jsonEffect->Put("radius", effectOption.radius.Value());
385 jsonEffect->Put("saturation", effectOption.saturation);
386 jsonEffect->Put("brightness", effectOption.brightness);
387 jsonEffect->Put("color", effectOption.color.ColorToString().c_str());
388 jsonEffect->Put("adaptiveColor", ADAPTIVE_COLOR[static_cast<int32_t>(effectOption.adaptiveColor)]);
389 jsonEffect->Put("policy", POLICY[static_cast<int>(effectOption.policy)]);
390 jsonEffect->Put("type", BLUR_TYPE[static_cast<int>(effectOption.blurType)]);
391 jsonEffect->Put("inactiveColor", effectOption.inactiveColor.ColorToString().c_str());
392 auto grayscale = "[0,0]";
393 if (effectOption.blurOption.grayscale.size() > 1) {
394 grayscale = ("[" + std::to_string(effectOption.blurOption.grayscale[0]) + "," +
395 std::to_string(effectOption.blurOption.grayscale[1]) + "]").c_str();
396 }
397 jsonEffect->Put("blurOption", grayscale);
398 return jsonEffect;
399 }
400 } // namespace OHOS::Ace::NG
401