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 
30 namespace OHOS::Ace::NG {
31 
32 class ACE_EXPORT TabContentPattern : public Pattern {
33     DECLARE_ACE_TYPE(TabContentPattern, Pattern);
34 
35 public:
TabContentPattern(const RefPtr<ShallowBuilder> & shallowBuilder)36     explicit TabContentPattern(const RefPtr<ShallowBuilder>& shallowBuilder)
37         : shallowBuilder_(shallowBuilder), tabBarParam_(std::string(""), std::string(""), nullptr)
38     {}
39     ~TabContentPattern() override = default;
40 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)41     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override
42     {
43         if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) {
44             auto host = GetHost();
45             CHECK_NULL_RETURN(host, false);
46             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
47             return true;
48         }
49         return false;
50     }
51 
IsAtomicNode()52     bool IsAtomicNode() const override
53     {
54         return false;
55     }
56 
IsMeasureBoundary()57     bool IsMeasureBoundary() const override
58     {
59         return false;
60     }
61 
UsResRegion()62     bool UsResRegion() override
63     {
64         return false;
65     }
66 
OnAttachToFrameNode()67     void OnAttachToFrameNode() override
68     {
69         auto host = GetHost();
70         CHECK_NULL_VOID(host);
71         host->GetRenderContext()->UpdateClipEdge(true);
72         FireWillShowEvent();
73         auto parentNode = host->GetAncestorNodeOfFrame();
74         CHECK_NULL_VOID(parentNode);
75         auto grandParentNode = parentNode->GetAncestorNodeOfFrame();
76         CHECK_NULL_VOID(grandParentNode);
77         if (grandParentNode->GetTag() == V2::TABS_ETS_TAG) {
78             auto tabLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(
79                 grandParentNode->GetLayoutProperty());
80             CHECK_NULL_VOID(tabLayoutProperty);
81             if (tabLayoutProperty->GetSafeAreaPaddingProperty()) {
82                 host->GetLayoutProperty()->UpdateSafeAreaExpandOpts({
83                     .type = SAFE_AREA_TYPE_SYSTEM,
84                     .edges = SAFE_AREA_EDGE_TOP + SAFE_AREA_EDGE_BOTTOM });
85             }
86         }
87     }
88 
CheckTabAnimateMode()89     void CheckTabAnimateMode()
90     {
91         if (!shallowBuilder_ || !firstTimeLayout_) {
92             return;
93         }
94 
95         // Check whether current tabcontent belongs to tab component.
96         auto tabContentNode = GetHost();
97         CHECK_NULL_VOID(tabContentNode);
98         auto parentNode = tabContentNode->GetAncestorNodeOfFrame();
99         CHECK_NULL_VOID(parentNode);
100         if (parentNode->GetTag() != V2::SWIPER_ETS_TAG) {
101             return;
102         }
103         auto grandParentNode = parentNode->GetAncestorNodeOfFrame();
104         CHECK_NULL_VOID(grandParentNode);
105         if (grandParentNode->GetTag() != V2::TABS_ETS_TAG) {
106             return;
107         }
108 
109         auto tabsPattern = grandParentNode->GetPattern<TabsPattern>();
110         CHECK_NULL_VOID(tabsPattern);
111         auto tabsLayoutProperty = grandParentNode->GetLayoutProperty<TabsLayoutProperty>();
112         CHECK_NULL_VOID(tabsLayoutProperty);
113         TabAnimateMode mode = tabsPattern->GetAnimateMode();
114         if (mode == TabAnimateMode::ACTION_FIRST
115             && !tabsLayoutProperty->GetHeightAutoValue(false)
116             && !tabsLayoutProperty->GetWidthAutoValue(false)) {
117             ACE_SCOPED_TRACE("TabContentMarkRenderDone");
118             /*
119              * Set render done only when tab's height&weight is not set to 'auto' and its animateMode
120              * is set to AnimateMode::ACTION_FIRST.
121              * Set render done before first layout, so to measure tabcontent and its children
122              * in two seperate frame.
123              */
124             shallowBuilder_->MarkIsExecuteDeepRenderDone(true);
125         }
126     }
127 
BeforeCreateLayoutWrapper()128     void BeforeCreateLayoutWrapper() override
129     {
130         if (firstTimeLayout_) {
131             CheckTabAnimateMode();
132             firstTimeLayout_ = false;
133         }
134 
135         if (shallowBuilder_ && !shallowBuilder_->IsExecuteDeepRenderDone()) {
136             shallowBuilder_->ExecuteDeepRender();
137             shallowBuilder_.Reset();
138         } else if (shallowBuilder_ && shallowBuilder_->IsExecuteDeepRenderDone()) {
139             auto pipeline = PipelineContext::GetCurrentContextSafely();
140             if (!pipeline) {
141                 shallowBuilder_->MarkIsExecuteDeepRenderDone(false);
142                 return;
143             }
144 
145             pipeline->AddAfterRenderTask([weak = WeakClaim(this), shallowBuilder = shallowBuilder_]() {
146                 CHECK_NULL_VOID(shallowBuilder);
147                 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
148                 auto pattern = weak.Upgrade();
149                 CHECK_NULL_VOID(pattern);
150                 auto host = pattern->GetHost();
151                 CHECK_NULL_VOID(host);
152                 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
153             });
154         }
155     }
156 
CreateLayoutProperty()157     RefPtr<LayoutProperty> CreateLayoutProperty() override
158     {
159         return MakeRefPtr<TabContentLayoutProperty>();
160     }
161 
SetTabBar(const std::string & text,const std::string & icon,const std::optional<TabBarSymbol> & tabBarSymbol,TabBarBuilderFunc && builder)162     void SetTabBar(const std::string& text, const std::string& icon,
163                    const std::optional<TabBarSymbol>& tabBarSymbol, TabBarBuilderFunc&& builder)
164     {
165         tabBarParam_.SetText(text);
166         tabBarParam_.SetIcon(icon);
167         tabBarParam_.SetSymbol(tabBarSymbol);
168         if (tabBarSymbol.has_value()) {
169             symbol_ = tabBarSymbol.value();
170         }
171         tabBarParam_.SetBuilder(move(builder));
172     }
173 
GetSymbol()174     const TabBarSymbol& GetSymbol()
175     {
176         return symbol_;
177     }
178 
GetTabBarParam()179     const TabBarParam& GetTabBarParam() const
180     {
181         return tabBarParam_;
182     }
183 
SetCustomTabBar(FrameNode * node)184     void SetCustomTabBar(FrameNode* node)
185     {
186         tabBarParam_.SetCustomNode(node);
187     }
188 
SetTabBarStyle(TabBarStyle tabBarStyle)189     void SetTabBarStyle(TabBarStyle tabBarStyle)
190     {
191         tabBarParam_.SetTabBarStyle(tabBarStyle);
192     }
193 
GetTabBarStyle()194     TabBarStyle GetTabBarStyle() const
195     {
196         return tabBarParam_.GetTabBarStyle();
197     }
198 
SetIndicatorStyle(const IndicatorStyle & indicatorStyle)199     void SetIndicatorStyle(const IndicatorStyle& indicatorStyle)
200     {
201         indicatorStyle_ = indicatorStyle;
202     }
203 
GetIndicatorStyle()204     const IndicatorStyle& GetIndicatorStyle() const
205     {
206         return indicatorStyle_;
207     }
208 
SetSelectedMode(SelectedMode selectedMode)209     void SetSelectedMode(SelectedMode selectedMode)
210     {
211         selectedMode_ = selectedMode;
212     }
213 
GetSelectedMode()214     SelectedMode GetSelectedMode() const
215     {
216         return selectedMode_;
217     }
218 
SetBoardStyle(const BoardStyle & boardStyle)219     void SetBoardStyle(const BoardStyle& boardStyle)
220     {
221         boardStyle_ = boardStyle;
222     }
223 
GetBoardStyle()224     const BoardStyle& GetBoardStyle() const
225     {
226         return boardStyle_;
227     }
228 
SetLabelStyle(const LabelStyle & labelStyle)229     void SetLabelStyle(const LabelStyle& labelStyle)
230     {
231         labelStyle_ = labelStyle;
232     }
233 
GetLabelStyle()234     const LabelStyle& GetLabelStyle() const
235     {
236         return labelStyle_;
237     }
238 
SetIconStyle(const IconStyle & iconStyle)239     void SetIconStyle(const IconStyle& iconStyle)
240     {
241         iconStyle_ = iconStyle;
242     }
243 
GetIconStyle()244     const IconStyle& GetIconStyle() const
245     {
246         return iconStyle_;
247     }
248 
SetPadding(const PaddingProperty & padding)249     void SetPadding(const PaddingProperty& padding)
250     {
251         padding_ = padding;
252     }
253 
GetPadding()254     const PaddingProperty& GetPadding() const
255     {
256         return padding_;
257     }
258 
SetUseLocalizedPadding(bool useLocalizedPadding)259     void SetUseLocalizedPadding(bool useLocalizedPadding)
260     {
261         useLocalizedPadding_ = useLocalizedPadding;
262     }
263 
GetUseLocalizedPadding()264     bool GetUseLocalizedPadding()
265     {
266         return useLocalizedPadding_;
267     }
268 
SetSymmetricExtensible(bool isExtensible)269     void SetSymmetricExtensible(bool isExtensible)
270     {
271         bottomTabBarStyle_.symmetricExtensible = isExtensible;
272     }
273 
SetLayoutMode(LayoutMode layoutMode)274     void SetLayoutMode(LayoutMode layoutMode)
275     {
276         bottomTabBarStyle_.layoutMode = layoutMode;
277     }
278 
SetVerticalAlign(FlexAlign verticalAlign)279     void SetVerticalAlign(FlexAlign verticalAlign)
280     {
281         bottomTabBarStyle_.verticalAlign = verticalAlign;
282     }
283 
SetId(const std::string & id)284     void SetId(const std::string& id)
285     {
286         tabBarInspectorId_ = id;
287     }
288 
GetId()289     const std::string& GetId() const
290     {
291         return tabBarInspectorId_;
292     }
293 
GetBottomTabBarStyle()294     const BottomTabBarStyle& GetBottomTabBarStyle() const
295     {
296         return bottomTabBarStyle_;
297     }
298 
DumpAdvanceInfo()299     void DumpAdvanceInfo() override
300     {
301         switch (selectedMode_) {
302             case SelectedMode::INDICATOR: {
303                 DumpLog::GetInstance().AddDesc("SelectedMode:INDICATOR");
304                 break;
305             }
306             case SelectedMode::BOARD: {
307                 DumpLog::GetInstance().AddDesc("SelectedMode:BOARD");
308                 break;
309             }
310             default: {
311                 break;
312             }
313         }
314     }
315 
CreateEventHub()316     RefPtr<EventHub> CreateEventHub() override
317     {
318         return MakeRefPtr<TabContentEventHub>();
319     }
320 
FireWillShowEvent()321     void FireWillShowEvent()
322     {
323         auto tabContentEventHub = GetEventHub<TabContentEventHub>();
324         CHECK_NULL_VOID(tabContentEventHub);
325         tabContentEventHub->FireWillShowEvent();
326     }
327 
FireWillHideEvent()328     void FireWillHideEvent()
329     {
330         auto tabContentEventHub = GetEventHub<TabContentEventHub>();
331         CHECK_NULL_VOID(tabContentEventHub);
332         tabContentEventHub->FireWillHideEvent();
333     }
334 
HasSubTabBarStyleNode()335     bool HasSubTabBarStyleNode() const
336     {
337         return customStyleNode_ != nullptr;
338     }
339 
SetCustomStyleNode(const RefPtr<FrameNode> & customStyleNode)340     void SetCustomStyleNode(const RefPtr<FrameNode>& customStyleNode)
341     {
342         customStyleNode_ = customStyleNode;
343     }
344 
FireCustomStyleNode()345     const RefPtr<FrameNode>& FireCustomStyleNode() const
346     {
347         return customStyleNode_;
348     }
349 
350 private:
351     RefPtr<ShallowBuilder> shallowBuilder_;
352     TabBarParam tabBarParam_;
353     IndicatorStyle indicatorStyle_;
354     SelectedMode selectedMode_ = SelectedMode::INDICATOR;
355     BoardStyle boardStyle_;
356     LabelStyle labelStyle_;
357     IconStyle iconStyle_;
358     PaddingProperty padding_;
359     std::string tabBarInspectorId_;
360     BottomTabBarStyle bottomTabBarStyle_;
361     RefPtr<FrameNode> customStyleNode_ = nullptr;
362     TabBarSymbol symbol_;
363 
364     bool firstTimeLayout_ = true;
365     bool useLocalizedPadding_ = false;
366 
367     ACE_DISALLOW_COPY_AND_MOVE(TabContentPattern);
368 };
369 
370 } // namespace OHOS::Ace::NG
371 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TABS_TAB_CONTENT_PATTERN_H
372