1 /*
2 * Copyright (c) 2021-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 "frameworks/bridge/common/dom/dom_tab_bar.h"
17
18 #include "core/components/tab_bar/tab_theme.h"
19 #include "core/components/theme/theme_manager.h"
20 #include "frameworks/bridge/common/dom/dom_type.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22
23 namespace OHOS::Ace::Framework {
24
DOMTabBar(NodeId nodeId,const std::string & nodeName)25 DOMTabBar::DOMTabBar(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
26 {
27 std::list<RefPtr<Component>> tabBars;
28 RefPtr<TabController> controller;
29 tabBarIndicator_ = AceType::MakeRefPtr<TabBarIndicatorComponent>();
30 tabBarChild_ = AceType::MakeRefPtr<TabBarComponent>(tabBars, controller, tabBarIndicator_);
31 }
32
InitializeStyle()33 void DOMTabBar::InitializeStyle()
34 {
35 RefPtr<TabTheme> theme = GetTheme<TabTheme>();
36 if (!theme) {
37 return;
38 }
39 if (boxComponent_) {
40 boxComponent_->SetColor(theme->GetBackgroundColor());
41 boxComponent_->SetHasBackgroundColor(true);
42 }
43 auto paddingDimension = theme->GetPadding();
44 padding_ = Edge(paddingDimension.Value(), 0.0, paddingDimension.Value(), 0.0, paddingDimension.Unit());
45 }
46
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)47 bool DOMTabBar::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
48 {
49 if (attr.first == DOM_TAB_BAR_MODE) {
50 tabBarMode_ = ConvertStrToTabBarMode(attr.second);
51 return true;
52 }
53 return false;
54 }
55
SetSpecializedStyle(const std::pair<std::string,std::string> & style)56 bool DOMTabBar::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
57 {
58 static const std::unordered_map<std::string, void (*)(const std::string&, DOMTabBar&)> styleOperators = {
59 { DOM_PADDING,
60 [](const std::string& val, DOMTabBar& node) {
61 node.padding_ = node.ParseEdge(val);
62 } },
63 { DOM_PADDING_END,
64 [](const std::string& val, DOMTabBar& node) {
65 if (node.IsRightToLeft()) {
66 node.padding_.SetLeft(node.ParseDimension(val));
67 } else {
68 node.padding_.SetRight(node.ParseDimension(val));
69 }
70 } },
71 { DOM_PADDING_LEFT,
72 [](const std::string& val, DOMTabBar& node) {
73 node.padding_.SetLeft(node.ParseDimension(val));
74 } },
75 { DOM_PADDING_RIGHT,
76 [](const std::string& val, DOMTabBar& node) {
77 node.padding_.SetRight(node.ParseDimension(val));
78 } },
79 { DOM_PADDING_START,
80 [](const std::string& val, DOMTabBar& node) {
81 if (node.IsRightToLeft()) {
82 node.padding_.SetRight(node.ParseDimension(val));
83 } else {
84 node.padding_.SetLeft(node.ParseDimension(val));
85 }
86 } },
87 { DOM_INDICATOR_COLOR,
88 [](const std::string& val, DOMTabBar& node) {
89 node.indicatorColor_= node.ParseColor(val);
90 }},
91 };
92 auto operatorIter = styleOperators.find(style.first);
93 if (operatorIter != styleOperators.end()) {
94 operatorIter->second(style.second, *this);
95 return true;
96 }
97 return false;
98 }
99
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)100 void DOMTabBar::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
101 {
102 if (!child) {
103 LOGE("Child is nullptr, add node failed, slot:%{public}d.", slot);
104 return;
105 }
106 if (tabBarChild_) {
107 LOGD("DOMTabBar Add Child in slot(=%{public}d)", slot);
108 tabBarChild_->InsertChild(slot, child->GetRootComponent());
109 }
110 }
111
UpdateIndex(uint32_t currentIndex)112 void DOMTabBar::UpdateIndex(uint32_t currentIndex)
113 {
114 uint32_t index = 0;
115 for (const auto& childNode : GetChildList()) {
116 if (index == currentIndex) {
117 OnChildActive(childNode, true);
118 } else if (index == lastIndex_) {
119 OnChildActive(childNode, false);
120 }
121 index++;
122 }
123 lastIndex_ = currentIndex;
124 }
125
OnMounted(const RefPtr<DOMNode> & parentNode)126 void DOMTabBar::OnMounted(const RefPtr<DOMNode>& parentNode)
127 {
128 if (!parentNode) {
129 LOGE("parentNode is nullptr, mount node failed");
130 return;
131 }
132 if (parentNode->GetTag() == DOM_NODE_TAG_TABS) {
133 const auto& parentNodeTmp = AceType::DynamicCast<DOMTabs>(parentNode);
134 if (!parentNodeTmp) {
135 LOGE("DynamicCast DOMTabs failed");
136 return;
137 }
138 lastIndex_ = parentNodeTmp->GetTabIndex();
139 controllerId_ = parentNodeTmp->GetTabControllerId();
140 const auto& controller = parentNodeTmp->GetTabController();
141 controller->SetIndexWithoutChangeContent(static_cast<int32_t>(lastIndex_));
142 tabBarChild_->SetController(controller);
143 PrepareChangeListener();
144 }
145 }
146
OnChildNodeRemoved(const RefPtr<DOMNode> & child)147 void DOMTabBar::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
148 {
149 if (!child) {
150 LOGE("Child is nullptr, remove node failed.");
151 return;
152 }
153 if (tabBarChild_) {
154 LOGD("DOMTabBar remove child");
155 tabBarChild_->RemoveChild(child->GetRootComponent());
156 }
157 }
158
ResetInitializedStyle()159 void DOMTabBar::ResetInitializedStyle()
160 {
161 if (!boxComponent_) {
162 LOGE("BoxComponent is null, reset style failed.");
163 return;
164 }
165 RefPtr<TabTheme> theme = GetTheme<TabTheme>();
166 if (theme) {
167 if(indicatorColor_.has_value()){
168 tabBarChild_->SetIndicatorColor(indicatorColor_.value());
169 }
170 tabBarChild_->InitStyle(theme);
171 if (vertical_) {
172 if (LessOrEqual(GetWidth().Value(), 0.0)) {
173 boxComponent_->SetWidth(theme->GetDefaultWidth().Value(), theme->GetDefaultWidth().Unit());
174 }
175 } else {
176 if (LessOrEqual(GetHeight().Value(), 0.0)) {
177 boxComponent_->SetHeight(theme->GetDefaultHeight().Value(), theme->GetDefaultHeight().Unit());
178 }
179 }
180 }
181 }
182
PrepareSpecializedComponent()183 void DOMTabBar::PrepareSpecializedComponent()
184 {
185 tabBarChild_->SetTextDirection(IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
186 tabBarChild_->SetMode(tabBarMode_);
187 const auto& parentNodeTmp = AceType::DynamicCast<DOMTabs>(parentNode_.Upgrade());
188 if (parentNodeTmp) {
189 vertical_ = parentNodeTmp->IsVertical();
190 }
191 tabBarChild_->SetVertical(vertical_);
192 ResetInitializedStyle();
193 tabBarChild_->SetPadding(padding_);
194 }
195
PrepareChangeListener()196 void DOMTabBar::PrepareChangeListener()
197 {
198 // used for initalized the active tabBarItem
199 auto weak = AceType::WeakClaim(this);
200 auto changeCallback = [weak](uint32_t currentIndex) {
201 auto tabBarNode = weak.Upgrade();
202 if (!tabBarNode) {
203 LOGE("get dom node failed!");
204 return;
205 }
206 tabBarNode->UpdateIndex(currentIndex);
207 };
208 auto changeMarker = BackEndEventManager<void(uint32_t)>::GetInstance().GetAvailableMarker();
209 BackEndEventManager<void(uint32_t)>::GetInstance().BindBackendEvent(changeMarker, changeCallback);
210 tabBarChild_->SetDomChangeEventId(changeMarker);
211 }
212
OnChildActive(const RefPtr<DOMNode> & node,bool active)213 void DOMTabBar::OnChildActive(const RefPtr<DOMNode>& node, bool active)
214 {
215 node->OnActive(active);
216 for (const auto& childNode : node->GetChildList()) {
217 childNode->OnActive(active);
218 }
219 }
220
ParseEdge(const std::string & value) const221 Edge DOMTabBar::ParseEdge(const std::string& value) const
222 {
223 Edge edge;
224 std::vector<std::string> offsets;
225 StringUtils::StringSplitter(value, ' ', offsets);
226 switch (offsets.size()) {
227 case 1:
228 edge.SetLeft(ParseDimension(offsets[0]));
229 edge.SetRight(ParseDimension(offsets[0]));
230 edge.SetTop(ParseDimension(offsets[0]));
231 edge.SetBottom(ParseDimension(offsets[0]));
232 break;
233 case 2:
234 edge.SetLeft(ParseDimension(offsets[0]));
235 edge.SetRight(ParseDimension(offsets[1]));
236 edge.SetTop(ParseDimension(offsets[0]));
237 edge.SetBottom(ParseDimension(offsets[0]));
238 break;
239 case 3:
240 edge.SetLeft(ParseDimension(offsets[1]));
241 edge.SetRight(ParseDimension(offsets[1]));
242 edge.SetTop(ParseDimension(offsets[0]));
243 edge.SetBottom(ParseDimension(offsets[2]));
244 break;
245 case 4:
246 edge.SetLeft(ParseDimension(offsets[3]));
247 edge.SetRight(ParseDimension(offsets[1]));
248 edge.SetTop(ParseDimension(offsets[0]));
249 edge.SetBottom(ParseDimension(offsets[2]));
250 break;
251 default:
252 break;
253 }
254 return edge;
255 }
256
257 } // namespace OHOS::Ace::Framework
258