1 /*
2 * Copyright (c) 2022 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 "bridge/declarative_frontend/jsview/models/tab_content_model_impl.h"
17
18 #include "bridge/declarative_frontend/jsview/js_container_base.h"
19 #include "bridge/declarative_frontend/view_stack_processor.h"
20
21 namespace OHOS::Ace::Framework {
22 namespace {
23
24 constexpr char DEFAULT_TAB_BAR_NAME[] = "TabBar";
25
26 } // namespace
27
Create()28 void TabContentModelImpl::Create()
29 {
30 std::list<RefPtr<Component>> components;
31 auto tabContentItemComponent = AceType::MakeRefPtr<V2::TabContentItemComponent>(components);
32 tabContentItemComponent->SetCrossAxisSize(CrossAxisSize::MAX);
33 ViewStackProcessor::GetInstance()->ClaimElementId(tabContentItemComponent);
34
35 RefPtr<V2::TabsComponent> tabsComponent = nullptr;
36 tabsComponent = AceType::DynamicCast<V2::TabsComponent>(ViewStackProcessor::GetInstance()->GetTopTabs());
37 CHECK_NULL_VOID(tabsComponent);
38 // GetTabsComponent used only by JSTabContent::SetTabBar
39 // To Find TabBarComponent eventually
40 tabContentItemComponent->SetTabsComponent(AceType::WeakClaim(AceType::RawPtr(tabsComponent)));
41
42 auto tabBar = tabsComponent->GetTabBarChild();
43 tabBar->AppendChild(CreateTabBarLabelComponent(tabContentItemComponent, std::string(DEFAULT_TAB_BAR_NAME)));
44
45 ViewStackProcessor::GetInstance()->Push(tabContentItemComponent);
46 auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
47 CHECK_NULL_VOID(box);
48 box->SetBoxClipFlag(true);
49 }
50
Create(std::function<void ()> && deepRenderFunc)51 void TabContentModelImpl::Create(std::function<void()>&& deepRenderFunc)
52 {
53 std::list<RefPtr<Component>> components;
54 auto tabContentItemComponent = AceType::MakeRefPtr<V2::TabContentItemComponent>(components);
55 tabContentItemComponent->SetCrossAxisSize(CrossAxisSize::MAX);
56 ViewStackProcessor::GetInstance()->ClaimElementId(tabContentItemComponent);
57
58 RefPtr<V2::TabsComponent> tabsComponent = nullptr;
59 ViewStackProcessor::GetInstance()->Push(tabContentItemComponent);
60 auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
61 if (box) {
62 box->SetBoxClipFlag(true);
63 }
64
65 auto jsWrapperFunc = [builder = std::move(deepRenderFunc)]() -> RefPtr<Component> {
66 CHECK_NULL_RETURN(builder, nullptr);
67 builder();
68 return ViewStackProcessor::GetInstance()->Finish();
69 };
70 tabContentItemComponent->SetBuilder(std::move(jsWrapperFunc));
71 }
72
Pop()73 void TabContentModelImpl::Pop()
74 {
75 JSContainerBase::Pop();
76 }
77
SetTabBar(const std::optional<std::string> & text,const std::optional<std::string> & icon,const std::optional<TabBarSymbol> & tabBarSymbol,std::function<void ()> && builder,bool useContentOnly)78 void TabContentModelImpl::SetTabBar(const std::optional<std::string>& text, const std::optional<std::string>& icon,
79 const std::optional<TabBarSymbol>& tabBarSymbol, std::function<void()>&& builder, bool useContentOnly)
80 {
81 auto tabContentItemComponent =
82 AceType::DynamicCast<V2::TabContentItemComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
83 CHECK_NULL_VOID(tabContentItemComponent);
84
85 auto weakTabs = tabContentItemComponent->GetTabsComponent();
86 // Full update: tabs and tabBar always exist
87 // Partial update: tabs and tabBar exist for initial render and nullptr for rerender
88 auto tabs = weakTabs.Upgrade();
89 auto tabBar = tabs ? tabs->GetTabBarChild() : nullptr;
90
91 if (!Container::IsCurrentUsePartialUpdate()) {
92 CHECK_NULL_VOID(tabs);
93 CHECK_NULL_VOID(tabBar);
94 }
95
96 RefPtr<Component> tabBarChild = nullptr;
97 if (useContentOnly) {
98 auto textVal = text.value_or(DEFAULT_TAB_BAR_NAME);
99 if (!Container::IsCurrentUsePartialUpdate()) {
100 tabBarChild = CreateTabBarLabelComponent(tabContentItemComponent, textVal);
101 } else {
102 tabContentItemComponent->SetBarText(textVal);
103 }
104 } else {
105 // For Partial Update ProcessTabBarXXX methods
106 // do not create any components for the tab bar items
107 // and return nullptr.
108 // Tab bar items created and added later by
109 // TabContentItemElementProxy class.
110 if (builder) {
111 tabBarChild = ProcessTabBarBuilderFunction(tabContentItemComponent, std::move(builder));
112 // Update tabBar always for full update and for initial render only for partial update
113 if (tabBar) {
114 tabBar->ResetIndicator();
115 tabBar->SetAlignment(Alignment::TOP_LEFT);
116 }
117 } else if (text.has_value() && icon.has_value()) {
118 tabBarChild = ProcessTabBarTextIconPair(tabContentItemComponent, text, icon);
119 } else if (text.has_value() && !icon.has_value()) {
120 tabBarChild = ProcessTabBarLabel(tabContentItemComponent, text);
121 }
122 }
123
124 if (!Container::IsCurrentUsePartialUpdate()) {
125 auto defaultTabChild = tabBar->GetChildren().back();
126 tabBar->RemoveChildDirectly(defaultTabChild);
127 tabBar->AppendChild(tabBarChild);
128 return;
129 }
130
131 // Partial Update only
132 if (tabContentItemComponent->GetBarElementId() == ElementRegister::UndefinedElementId) {
133 const auto id = ElementRegister::GetInstance()->MakeUniqueId();
134 tabContentItemComponent->SetBarElementId(id);
135 }
136 }
137
ProcessTabBarBuilderFunction(RefPtr<V2::TabContentItemComponent> & tabContent,std::function<void ()> && builderFunc)138 RefPtr<Component> TabContentModelImpl::ProcessTabBarBuilderFunction(
139 RefPtr<V2::TabContentItemComponent>& tabContent, std::function<void()>&& builderFunc)
140 {
141 CHECK_NULL_RETURN(builderFunc, nullptr);
142 tabContent->SetBarText("custom");
143 if (Container::IsCurrentUsePartialUpdate()) {
144 auto jsWrapperFunc = [builder = std::move(builderFunc)]() -> RefPtr<Component> {
145 builder();
146 return ViewStackProcessor::GetInstance()->Finish();
147 };
148 tabContent->SetBarBuilder(jsWrapperFunc);
149 return nullptr;
150 }
151
152 ScopedViewStackProcessor builderViewStackProcessor;
153 builderFunc();
154 RefPtr<Component> builderGeneratedRootComponent = ViewStackProcessor::GetInstance()->Finish();
155 return builderGeneratedRootComponent;
156 }
157
CreateTabBarLabelComponent(RefPtr<V2::TabContentItemComponent> & tabContent,const std::string & labelStr)158 RefPtr<Component> TabContentModelImpl::CreateTabBarLabelComponent(
159 RefPtr<V2::TabContentItemComponent>& tabContent, const std::string& labelStr)
160 {
161 tabContent->SetBarText(labelStr);
162 return TabBarItemComponent::BuildWithTextIcon(labelStr, std::string());
163 }
164
ProcessTabBarLabel(RefPtr<V2::TabContentItemComponent> & tabContent,const std::optional<std::string> & textVal)165 RefPtr<Component> TabContentModelImpl::ProcessTabBarLabel(
166 RefPtr<V2::TabContentItemComponent>& tabContent, const std::optional<std::string>& textVal)
167 {
168 std::string textStr = textVal.value_or(DEFAULT_TAB_BAR_NAME);
169 tabContent->SetBarText(textStr);
170
171 if (!Container::IsCurrentUsePartialUpdate()) {
172 return CreateTabBarLabelComponent(tabContent, textStr);
173 }
174 return nullptr;
175 }
176
ProcessTabBarTextIconPair(RefPtr<V2::TabContentItemComponent> & tabContent,const std::optional<std::string> & textVal,const std::optional<std::string> & iconVal)177 RefPtr<Component> TabContentModelImpl::ProcessTabBarTextIconPair(RefPtr<V2::TabContentItemComponent>& tabContent,
178 const std::optional<std::string>& textVal, const std::optional<std::string>& iconVal)
179 {
180 if (!iconVal.has_value()) {
181 return ProcessTabBarLabel(tabContent, textVal);
182 }
183
184 auto textStr = textVal.value_or(DEFAULT_TAB_BAR_NAME);
185 tabContent->SetBarText(textStr);
186 tabContent->SetBarIcon(iconVal.value());
187
188 if (!Container::IsCurrentUsePartialUpdate()) {
189 return TabBarItemComponent::BuildWithTextIcon(textStr, iconVal.value());
190 }
191 return nullptr;
192 }
193
194 } // namespace OHOS::Ace::Framework
195