• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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