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