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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H 18 19 #include "base/log/dump_log.h" 20 #include "base/memory/referenced.h" 21 #include "base/utils/noncopyable.h" 22 #include "core/components_ng/event/event_hub.h" 23 #include "core/components_ng/pattern/pattern.h" 24 #include "core/components_ng/pattern/tabs/tabs_pattern.h" 25 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h" 26 #include "core/components_ng/pattern/tabs/tab_content_event_hub.h" 27 #include "core/components_ng/pattern/tabs/tab_content_layout_property.h" 28 #include "core/components_ng/syntax/shallow_builder.h" 29 #include "core/components_ng/pattern/tabs/tab_content_node.h" 30 #include "core/components_ng/pattern/tabs/tabs_node.h" 31 32 namespace OHOS::Ace::NG { 33 34 class ACE_EXPORT TabContentPattern : public Pattern { 35 DECLARE_ACE_TYPE(TabContentPattern, Pattern); 36 37 public: TabContentPattern(const RefPtr<ShallowBuilder> & shallowBuilder)38 explicit TabContentPattern(const RefPtr<ShallowBuilder>& shallowBuilder) 39 : shallowBuilder_(shallowBuilder), tabBarParam_(std::string(""), std::string(""), nullptr) 40 {} 41 ~TabContentPattern() override = default; 42 OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)43 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override 44 { 45 if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) { 46 auto host = GetHost(); 47 CHECK_NULL_RETURN(host, false); 48 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); 49 return true; 50 } 51 return false; 52 } 53 IsAtomicNode()54 bool IsAtomicNode() const override 55 { 56 return false; 57 } 58 IsMeasureBoundary()59 bool IsMeasureBoundary() const override 60 { 61 return false; 62 } 63 UsResRegion()64 bool UsResRegion() override 65 { 66 return false; 67 } 68 OnAttachToFrameNode()69 void OnAttachToFrameNode() override 70 { 71 auto host = GetHost(); 72 CHECK_NULL_VOID(host); 73 host->GetRenderContext()->UpdateClipEdge(true); 74 FireWillShowEvent(); 75 auto parentNode = host->GetAncestorNodeOfFrame(false); 76 CHECK_NULL_VOID(parentNode); 77 auto grandParentNode = parentNode->GetAncestorNodeOfFrame(false); 78 CHECK_NULL_VOID(grandParentNode); 79 if (grandParentNode->GetTag() == V2::TABS_ETS_TAG) { 80 auto tabLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>( 81 grandParentNode->GetLayoutProperty()); 82 CHECK_NULL_VOID(tabLayoutProperty); 83 if (tabLayoutProperty->GetSafeAreaPaddingProperty()) { 84 host->GetLayoutProperty()->UpdateSafeAreaExpandOpts({ 85 .type = SAFE_AREA_TYPE_SYSTEM, 86 .edges = SAFE_AREA_EDGE_TOP + SAFE_AREA_EDGE_BOTTOM }); 87 } 88 } 89 90 } 91 CheckTabAnimateMode()92 void CheckTabAnimateMode() 93 { 94 if (!shallowBuilder_ || !(firstTimeLayout_ || secondTimeLayout_)) { 95 return; 96 } 97 98 // Check whether current tabcontent belongs to tab component. 99 auto tabContentNode = GetHost(); 100 CHECK_NULL_VOID(tabContentNode); 101 auto parentNode = tabContentNode->GetAncestorNodeOfFrame(false); 102 CHECK_NULL_VOID(parentNode); 103 if (parentNode->GetTag() != V2::SWIPER_ETS_TAG) { 104 return; 105 } 106 auto grandParentNode = parentNode->GetAncestorNodeOfFrame(false); 107 CHECK_NULL_VOID(grandParentNode); 108 if (grandParentNode->GetTag() != V2::TABS_ETS_TAG) { 109 return; 110 } 111 112 auto tabsPattern = grandParentNode->GetPattern<TabsPattern>(); 113 CHECK_NULL_VOID(tabsPattern); 114 auto tabsLayoutProperty = grandParentNode->GetLayoutProperty<TabsLayoutProperty>(); 115 CHECK_NULL_VOID(tabsLayoutProperty); 116 TabAnimateMode mode = tabsPattern->GetAnimateMode(); 117 if ((mode == TabAnimateMode::ACTION_FIRST || mode == TabAnimateMode::ACTION_FIRST_WITH_JUMP) 118 && !tabsLayoutProperty->GetHeightAutoValue(false) 119 && !tabsLayoutProperty->GetWidthAutoValue(false)) { 120 ACE_SCOPED_TRACE("TabContentMarkRenderDone"); 121 /* 122 * Set render done only when tab's height&weight is not set to 'auto' and its animateMode 123 * is set to AnimateMode::ACTION_FIRST. 124 * Set render done before first layout, so to measure tabcontent and its children 125 * in two seperate frame. 126 */ 127 shallowBuilder_->MarkIsExecuteDeepRenderDone(true); 128 } 129 } 130 CleanChildren()131 void CleanChildren() 132 { 133 auto host = GetHost(); 134 CHECK_NULL_VOID(host); 135 if (host->GetChildren().empty()) { 136 return; 137 } 138 host->Clean(); 139 secondTimeLayout_ = true; 140 CHECK_NULL_VOID(shallowBuilder_); 141 shallowBuilder_->MarkIsExecuteDeepRenderDone(false); 142 } 143 BeforeCreateLayoutWrapper()144 void BeforeCreateLayoutWrapper() override 145 { 146 if (firstTimeLayout_ || secondTimeLayout_) { 147 CheckTabAnimateMode(); 148 } 149 150 if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) { 151 shallowBuilder_->ExecuteDeepRender(); 152 if (secondTimeLayout_) { 153 auto host = GetHost(); 154 CHECK_NULL_VOID(host); 155 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); 156 } 157 } else if ((firstTimeLayout_ || secondTimeLayout_) && shallowBuilder_ && 158 shallowBuilder_->IsExecuteDeepRenderDone()) { 159 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck(); 160 if (!pipeline) { 161 shallowBuilder_->MarkIsExecuteDeepRenderDone(false); 162 return; 163 } 164 165 pipeline->AddAfterRenderTask([weak = WeakClaim(this), shallowBuilder = shallowBuilder_]() { 166 CHECK_NULL_VOID(shallowBuilder); 167 shallowBuilder->MarkIsExecuteDeepRenderDone(false); 168 auto pattern = weak.Upgrade(); 169 CHECK_NULL_VOID(pattern); 170 auto host = pattern->GetHost(); 171 CHECK_NULL_VOID(host); 172 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); 173 }); 174 } 175 firstTimeLayout_ = false; 176 secondTimeLayout_ = false; 177 } 178 CreateLayoutProperty()179 RefPtr<LayoutProperty> CreateLayoutProperty() override 180 { 181 return MakeRefPtr<TabContentLayoutProperty>(); 182 } 183 SetTabBar(const std::string & text,const std::string & icon,const std::optional<TabBarSymbol> & tabBarSymbol,TabBarBuilderFunc && builder)184 void SetTabBar(const std::string& text, const std::string& icon, 185 const std::optional<TabBarSymbol>& tabBarSymbol, TabBarBuilderFunc&& builder) 186 { 187 tabBarParam_.SetText(text); 188 tabBarParam_.SetIcon(icon); 189 tabBarParam_.SetSymbol(tabBarSymbol); 190 if (tabBarSymbol.has_value()) { 191 symbol_ = tabBarSymbol.value(); 192 } 193 tabBarParam_.SetBuilder(move(builder)); 194 } 195 SetTabBarWithContent(const RefPtr<NG::UINode> & content)196 void SetTabBarWithContent(const RefPtr<NG::UINode>& content) 197 { 198 tabBarParam_.SetContent(content); 199 } 200 GetSymbol()201 const TabBarSymbol& GetSymbol() 202 { 203 return symbol_; 204 } 205 GetTabBarParam()206 const TabBarParam& GetTabBarParam() const 207 { 208 return tabBarParam_; 209 } 210 UpdateTabBarParamText(const std::string & text)211 void UpdateTabBarParamText(const std::string &text) 212 { 213 tabBarParam_.SetText(text); 214 } 215 UpdateTabBarParamIcon(const std::string & icon)216 void UpdateTabBarParamIcon(const std::string &icon) 217 { 218 tabBarParam_.SetIcon(icon); 219 } 220 SetCustomTabBar(FrameNode * node)221 void SetCustomTabBar(FrameNode* node) 222 { 223 tabBarParam_.SetCustomNode(node); 224 } 225 SetTabBarStyle(TabBarStyle tabBarStyle)226 void SetTabBarStyle(TabBarStyle tabBarStyle) 227 { 228 tabBarParam_.SetTabBarStyle(tabBarStyle); 229 } 230 GetTabBarStyle()231 TabBarStyle GetTabBarStyle() const 232 { 233 return tabBarParam_.GetTabBarStyle(); 234 } 235 SetIndicatorStyle(const IndicatorStyle & indicatorStyle)236 void SetIndicatorStyle(const IndicatorStyle& indicatorStyle) 237 { 238 indicatorStyle_ = indicatorStyle; 239 } 240 GetIndicatorStyle()241 const IndicatorStyle& GetIndicatorStyle() const 242 { 243 return indicatorStyle_; 244 } 245 SetSelectedMode(SelectedMode selectedMode)246 void SetSelectedMode(SelectedMode selectedMode) 247 { 248 selectedMode_ = selectedMode; 249 } 250 GetSelectedMode()251 SelectedMode GetSelectedMode() const 252 { 253 return selectedMode_; 254 } 255 SetBoardStyle(const BoardStyle & boardStyle)256 void SetBoardStyle(const BoardStyle& boardStyle) 257 { 258 boardStyle_ = boardStyle; 259 } 260 GetBoardStyle()261 const BoardStyle& GetBoardStyle() const 262 { 263 return boardStyle_; 264 } 265 SetLabelStyle(const LabelStyle & labelStyle)266 void SetLabelStyle(const LabelStyle& labelStyle) 267 { 268 labelStyle_ = labelStyle; 269 } 270 GetLabelStyle()271 const LabelStyle& GetLabelStyle() const 272 { 273 return labelStyle_; 274 } 275 SetIconStyle(const IconStyle & iconStyle)276 void SetIconStyle(const IconStyle& iconStyle) 277 { 278 iconStyle_ = iconStyle; 279 } 280 GetIconStyle()281 const IconStyle& GetIconStyle() const 282 { 283 return iconStyle_; 284 } 285 SetPadding(const PaddingProperty & padding)286 void SetPadding(const PaddingProperty& padding) 287 { 288 padding_ = padding; 289 } 290 GetPadding()291 const PaddingProperty& GetPadding() const 292 { 293 return padding_; 294 } 295 SetUseLocalizedPadding(bool useLocalizedPadding)296 void SetUseLocalizedPadding(bool useLocalizedPadding) 297 { 298 useLocalizedPadding_ = useLocalizedPadding; 299 } 300 GetUseLocalizedPadding()301 bool GetUseLocalizedPadding() 302 { 303 return useLocalizedPadding_; 304 } 305 SetSymmetricExtensible(bool isExtensible)306 void SetSymmetricExtensible(bool isExtensible) 307 { 308 bottomTabBarStyle_.symmetricExtensible = isExtensible; 309 } 310 SetLayoutMode(LayoutMode layoutMode)311 void SetLayoutMode(LayoutMode layoutMode) 312 { 313 bottomTabBarStyle_.layoutMode = layoutMode; 314 } 315 SetVerticalAlign(FlexAlign verticalAlign)316 void SetVerticalAlign(FlexAlign verticalAlign) 317 { 318 bottomTabBarStyle_.verticalAlign = verticalAlign; 319 } 320 SetId(const std::string & id)321 void SetId(const std::string& id) 322 { 323 tabBarInspectorId_ = id; 324 } 325 GetId()326 const std::string& GetId() const 327 { 328 return tabBarInspectorId_; 329 } 330 GetBottomTabBarStyle()331 const BottomTabBarStyle& GetBottomTabBarStyle() const 332 { 333 return bottomTabBarStyle_; 334 } 335 DumpAdvanceInfo()336 void DumpAdvanceInfo() override 337 { 338 switch (selectedMode_) { 339 case SelectedMode::INDICATOR: { 340 DumpLog::GetInstance().AddDesc("SelectedMode:INDICATOR"); 341 break; 342 } 343 case SelectedMode::BOARD: { 344 DumpLog::GetInstance().AddDesc("SelectedMode:BOARD"); 345 break; 346 } 347 default: { 348 break; 349 } 350 } 351 } 352 CreateEventHub()353 RefPtr<EventHub> CreateEventHub() override 354 { 355 return MakeRefPtr<TabContentEventHub>(); 356 } 357 FireWillShowEvent()358 void FireWillShowEvent() 359 { 360 auto tabContentEventHub = GetOrCreateEventHub<TabContentEventHub>(); 361 CHECK_NULL_VOID(tabContentEventHub); 362 tabContentEventHub->FireWillShowEvent(); 363 } 364 FireWillHideEvent()365 void FireWillHideEvent() 366 { 367 auto tabContentEventHub = GetOrCreateEventHub<TabContentEventHub>(); 368 CHECK_NULL_VOID(tabContentEventHub); 369 tabContentEventHub->FireWillHideEvent(); 370 } 371 HasSubTabBarStyleNode()372 bool HasSubTabBarStyleNode() const 373 { 374 return customStyleNode_ != nullptr; 375 } 376 SetCustomStyleNode(const RefPtr<FrameNode> & customStyleNode)377 void SetCustomStyleNode(const RefPtr<FrameNode>& customStyleNode) 378 { 379 customStyleNode_ = customStyleNode; 380 } 381 FireCustomStyleNode()382 const RefPtr<FrameNode>& FireCustomStyleNode() const 383 { 384 return customStyleNode_; 385 } 386 DumpAdvanceInfo(std::unique_ptr<JsonValue> & json)387 void DumpAdvanceInfo(std::unique_ptr<JsonValue>& json) override 388 { 389 switch (selectedMode_) { 390 case SelectedMode::INDICATOR: { 391 json->Put("SelectedMode", "INDICATOR"); 392 break; 393 } 394 case SelectedMode::BOARD: { 395 json->Put("SelectedMode", "BOARD"); 396 break; 397 } 398 default: { 399 break; 400 } 401 } 402 } 403 OnColorModeChange(uint32_t colorMode)404 void OnColorModeChange(uint32_t colorMode) override 405 { 406 CHECK_NULL_VOID(SystemProperties::ConfigChangePerform()); 407 Pattern::OnColorModeChange(colorMode); 408 auto tabContentNode = AceType::DynamicCast<TabContentNode>(GetHost()); 409 CHECK_NULL_VOID(tabContentNode); 410 tabContentNode->UpdataTabBarItem(); 411 auto host = GetHost(); 412 CHECK_NULL_VOID(host); 413 auto pipeline = host->GetContextWithCheck(); 414 CHECK_NULL_VOID(pipeline); 415 auto theme = pipeline->GetTheme<TabTheme>(); 416 CHECK_NULL_VOID(theme); 417 auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent()); 418 CHECK_NULL_VOID(tabsNode); 419 auto layout = tabsNode->GetLayoutProperty<TabContentLayoutProperty>(); 420 CHECK_NULL_VOID(layout); 421 auto tabContentPattern = tabsNode->GetPattern<TabContentPattern>(); 422 CHECK_NULL_VOID(tabContentPattern); 423 if (!layout->HasIndicatorColorSetByUser() || 424 (layout->HasIndicatorColorSetByUser() && !layout->GetIndicatorColorSetByUserValue())) { 425 auto currentIndicator = tabContentPattern->GetIndicatorStyle(); 426 currentIndicator.color = theme->GetActiveIndicatorColor(); 427 tabContentPattern->SetIndicatorStyle(currentIndicator); 428 } 429 if (!layout->HasLabelSelectedColorSetByUser() || 430 (layout->HasLabelSelectedColorSetByUser() && !layout->GetLabelSelectedColorSetByUserValue())) { 431 auto currentLabelStyle = tabContentPattern->GetLabelStyle(); 432 currentLabelStyle.selectedColor = theme->GetSubTabTextOnColor(); 433 tabContentPattern->SetLabelStyle(currentLabelStyle); 434 } 435 if (!layout->HasLabelUnselectedColorSetByUser() || 436 (layout->HasLabelUnselectedColorSetByUser() && !layout->GetLabelUnselectedColorSetByUserValue())) { 437 auto currentLabelStyle = tabContentPattern->GetLabelStyle(); 438 currentLabelStyle.unselectedColor = theme->GetSubTabTextOffColor(); 439 tabContentPattern->SetLabelStyle(currentLabelStyle); 440 } 441 if (!layout->HasIconSelectedColorSetByUser() || 442 (layout->HasIconSelectedColorSetByUser() && !layout->GetIconSelectedColorSetByUserValue())) { 443 auto currentIconStyle = tabContentPattern->GetIconStyle(); 444 currentIconStyle.selectedColor = theme->GetBottomTabTextOn(); 445 tabContentPattern->SetIconStyle(currentIconStyle); 446 } 447 if (!layout->HasIconUnselectedColorSetByUser() || 448 (layout->HasIconUnselectedColorSetByUser() && !layout->GetIconUnselectedColorSetByUserValue())) { 449 auto currentIconStyle = tabContentPattern->GetIconStyle(); 450 currentIconStyle.unselectedColor = theme->GetBottomTabTextOff(); 451 tabContentPattern->SetIconStyle(currentIconStyle); 452 } 453 } 454 GetAxis()455 Axis GetAxis() const 456 { 457 auto host = GetHost(); 458 CHECK_NULL_RETURN(host, Axis::HORIZONTAL); 459 auto swiperNode = host->GetAncestorNodeOfFrame(false); 460 CHECK_NULL_RETURN(swiperNode, Axis::HORIZONTAL); 461 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>(); 462 CHECK_NULL_RETURN(swiperPattern, Axis::HORIZONTAL); 463 return swiperPattern->GetDirection(); 464 } 465 ChildPreMeasureHelperEnabled()466 bool ChildPreMeasureHelperEnabled() override 467 { 468 return true; 469 } PostponedTaskForIgnoreEnabled()470 bool PostponedTaskForIgnoreEnabled() override 471 { 472 return true; 473 } 474 NeedCustomizeSafeAreaPadding()475 bool NeedCustomizeSafeAreaPadding() override 476 { 477 return true; 478 } 479 CustomizeSafeAreaPadding(PaddingPropertyF safeAreaPadding,bool needRotate)480 PaddingPropertyF CustomizeSafeAreaPadding(PaddingPropertyF safeAreaPadding, bool needRotate) override 481 { 482 bool isVertical = GetAxis() == Axis::VERTICAL; 483 if (needRotate) { 484 isVertical = !isVertical; 485 } 486 if (isVertical) { 487 safeAreaPadding.top = std::nullopt; 488 safeAreaPadding.bottom = std::nullopt; 489 } else { 490 safeAreaPadding.left = std::nullopt; 491 safeAreaPadding.right = std::nullopt; 492 } 493 return safeAreaPadding; 494 } 495 ChildTentativelyLayouted()496 bool ChildTentativelyLayouted() override 497 { 498 return true; 499 } 500 501 bool AccumulatingTerminateHelper(RectF& adjustingRect, ExpandEdges& totalExpand, bool fromSelf = false, 502 LayoutSafeAreaType ignoreType = NG::LAYOUT_SAFE_AREA_TYPE_SYSTEM) override 503 { 504 auto host = GetHost(); 505 CHECK_NULL_RETURN(host, false); 506 if (host->IsScrollableAxisInsensitive()) { 507 return false; 508 } 509 auto expandFromSwiper = host->GetAccumulatedSafeAreaExpand( 510 false, { .edges = GetAxis() == Axis::VERTICAL ? LAYOUT_SAFE_AREA_EDGE_HORIZONTAL 511 : LAYOUT_SAFE_AREA_EDGE_VERTICAL }); 512 auto geometryNode = host->GetGeometryNode(); 513 CHECK_NULL_RETURN(geometryNode, false); 514 auto frameRect = geometryNode->GetFrameRect(); 515 totalExpand = totalExpand.Plus(AdjacentExpandToRect(adjustingRect, expandFromSwiper, frameRect)); 516 return true; 517 } 518 519 private: 520 RefPtr<ShallowBuilder> shallowBuilder_; 521 TabBarParam tabBarParam_; 522 IndicatorStyle indicatorStyle_; 523 SelectedMode selectedMode_ = SelectedMode::INDICATOR; 524 BoardStyle boardStyle_; 525 LabelStyle labelStyle_; 526 IconStyle iconStyle_; 527 PaddingProperty padding_; 528 std::string tabBarInspectorId_; 529 BottomTabBarStyle bottomTabBarStyle_; 530 RefPtr<FrameNode> customStyleNode_ = nullptr; 531 TabBarSymbol symbol_; 532 533 bool firstTimeLayout_ = true; 534 bool secondTimeLayout_ = false; 535 bool useLocalizedPadding_ = false; 536 537 ACE_DISALLOW_COPY_AND_MOVE(TabContentPattern); 538 }; 539 540 } // namespace OHOS::Ace::NG 541 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H 542