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_select.h"
17
18 #include "base/utils/linear_map.h"
19 #include "base/utils/utils.h"
20 #include "frameworks/bridge/common/dom/dom_option.h"
21 #include "frameworks/bridge/common/dom/dom_reflect_map.h"
22 #include "frameworks/bridge/common/utils/utils.h"
23
24 namespace OHOS::Ace::Framework {
25
IsParentNavigation() const26 bool DOMSelect::IsParentNavigation() const
27 {
28 auto parent = GetParentNode();
29 if (!parent) {
30 LOGE("parent of dom select is null.");
31 return false;
32 }
33 return parent->GetTag() == DOM_NODE_TAG_NAVIGATION_BAR;
34 }
35
DOMSelect(NodeId nodeId,const std::string & nodeName)36 DOMSelect::DOMSelect(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
37 {
38 selectComponent_ = AceType::MakeRefPtr<SelectComponent>();
39 tipText_ = AceType::MakeRefPtr<TextComponent>("");
40 selectComponent_->SetTipText(tipText_);
41 #if defined(PREVIEW)
42 selectComponent_->SetNodeId(nodeId);
43 #endif
44 }
45
ResetInitializedStyle()46 void DOMSelect::ResetInitializedStyle()
47 {
48 InitializeStyle();
49 }
50
InitializeStyle()51 void DOMSelect::InitializeStyle()
52 {
53 if (!selectComponent_) {
54 LOGE("selectComponent is null");
55 return;
56 }
57 selectComponent_->InitTheme(GetThemeManager());
58 theme_ = GetTheme<SelectTheme>();
59 if (theme_ && selectComponent_) {
60 selectComponent_->SetClickedColor(theme_->GetClickedColor());
61 selectComponent_->SetDisabledColor(theme_->GetDisabledColor());
62 selectComponent_->SetSelectedColor(theme_->GetSelectedColor());
63 selectComponent_->SetOptionSize(theme_->GetOptionSize());
64 selectComponent_->SetRRectSize(theme_->GetRRectSize());
65 selectComponent_->SetPopupBorderWidth(theme_->GetPopupBorderWidth());
66 selectComponent_->SetPopupShadowWidth(theme_->GetPopupShadowWidth());
67 selectComponent_->SetFontFamily(theme_->GetFontFamily());
68 selectComponent_->SetFontSize(theme_->GetFontSize());
69 selectComponent_->SetAllowScale(theme_->IsAllowScale());
70 selectComponent_->SetTextColor(theme_->GetFontColor());
71 selectComponent_->SetFontWeight(FontWeight::W500);
72 selectComponent_->SetTextDecoration(theme_->GetTextDecoration());
73 selectComponent_->SetBackgroundColor(Color::TRANSPARENT);
74 }
75 }
76
UpdateBoxSize(const CalcDimension & width,const CalcDimension & height)77 void DOMSelect::UpdateBoxSize(const CalcDimension& width, const CalcDimension& height)
78 {
79 if (!selectComponent_) {
80 return;
81 }
82
83 if (width.Unit() != DimensionUnit::PERCENT && height.Unit() != DimensionUnit::PERCENT) {
84 selectComponent_->SetInnerSize(width, height);
85 return;
86 }
87
88 if (width.Unit() == DimensionUnit::PERCENT && height.Unit() == DimensionUnit::PERCENT) {
89 DOMNode::UpdateBoxSize(width, height);
90 selectComponent_->SetInnerSize(100.0_pct, 100.0_pct);
91 return;
92 }
93
94 if (width.Unit() == DimensionUnit::PERCENT) {
95 DOMNode::UpdateBoxSize(width, height);
96 selectComponent_->SetInnerSize(100.0_pct, height);
97 return;
98 }
99
100 DOMNode::UpdateBoxSize(width, height);
101 selectComponent_->SetInnerSize(100.0_pct, 100.0_pct);
102 }
103
UpdateBoxPadding(const Edge & padding)104 void DOMSelect::UpdateBoxPadding(const Edge& padding)
105 {
106 if (!selectComponent_) {
107 return;
108 }
109
110 selectComponent_->SetInnerPadding(padding);
111 }
112
UpdateBoxBorder(const Border & border)113 void DOMSelect::UpdateBoxBorder(const Border& border)
114 {
115 if (!selectComponent_) {
116 return;
117 }
118
119 selectComponent_->SetInnerBorder(border);
120 }
121
AddSpecializedEvent(int32_t pageId,const std::string & event)122 bool DOMSelect::AddSpecializedEvent(int32_t pageId, const std::string& event)
123 {
124 if (event == DOM_CHANGE) {
125 onChanged_ = EventMarker(GetNodeIdForEvent(), event, pageId);
126 selectComponent_->SetOnChanged(onChanged_);
127 return true;
128 }
129 return false;
130 }
131
SetSpecializedStyle(const std::pair<std::string,std::string> & style)132 bool DOMSelect::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
133 {
134 if (IsParentNavigation()) {
135 // not support style setting for navigation.
136 return true;
137 }
138
139 static const LinearMapNode<void (*)(const std::string&, const DOMSelect&, SelectComponent&)>
140 selectStyleOperators[] = {
141 { DOM_TEXT_ALLOW_SCALE, [](const std::string& val, const DOMSelect& node,
142 SelectComponent& select) { select.SetAllowScale(StringToBool(val)); } },
143 { DOM_BACKGROUND_COLOR, [](const std::string& val, const DOMSelect& node,
144 SelectComponent& select) { select.SetBackgroundColor(node.ParseColor(val)); } },
145 { DOM_TEXT_COLOR, [](const std::string& val, const DOMSelect& node,
146 SelectComponent& select) { select.SetTextColor(node.ParseColor(val)); } },
147 { DOM_TEXT_FONT_FAMILY, [](const std::string& val, const DOMSelect& node,
148 SelectComponent& select) { select.SetFontFamily(val); } },
149 { DOM_TEXT_FONT_SIZE,
150 [](const std::string& val, const DOMSelect& node, SelectComponent& select) {
151 select.SetFontSize(node.ParseDimension(val));
152 select.SetIsFontSetFlag(true);
153 } },
154 { DOM_TEXT_FONT_WEIGHT, [](const std::string& val, const DOMSelect& node,
155 SelectComponent& select) { select.SetFontWeight(ConvertStrToFontWeight(val)); } },
156 { DOM_TEXT_DECORATION,
157 [](const std::string& val, const DOMSelect& node, SelectComponent& select) {
158 select.SetTextDecoration(ConvertStrToTextDecoration(val));
159 } },
160 };
161 auto operatorIter =
162 BinarySearchFindIndex(selectStyleOperators, ArraySize(selectStyleOperators), style.first.c_str());
163 if (operatorIter != -1) {
164 selectStyleOperators[operatorIter].value(style.second, *this, *selectComponent_);
165 return true;
166 }
167 return false;
168 }
169
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)170 void DOMSelect::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
171 {
172 if (!child || child->GetTag() != DOM_NODE_TAG_OPTION) {
173 LOGE("DOMSelect child is not correct");
174 return;
175 }
176
177 auto option = AceType::DynamicCast<DOMOption>(child);
178 if (option) {
179 auto optionComponent = AceType::DynamicCast<OptionComponent>(option->GetSpecializedComponent());
180 if (!optionComponent) {
181 return;
182 }
183 if (!selectComponent_->GetSelectOptionCount() || optionComponent->GetSelected()) {
184 auto text = optionComponent->GetText();
185 if (text) {
186 tipText_->SetData(text->GetData());
187 } else {
188 LOGE("text of option component is null.");
189 tipText_->SetData("");
190 }
191 }
192 if (slot < 0) {
193 selectComponent_->AppendSelectOption(optionComponent);
194 } else {
195 selectComponent_->InsertSelectOption(optionComponent, static_cast<uint32_t>(slot));
196 }
197 LOGD("DOMSelect %{public}s, appendChild %{public}s", GetTag().c_str(), child->GetTag().c_str());
198 }
199 }
200
OnChildNodeRemoved(const RefPtr<DOMNode> & child)201 void DOMSelect::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
202 {
203 if (!child || !selectComponent_) {
204 return;
205 }
206
207 auto option = AceType::DynamicCast<OptionComponent>(child->GetSpecializedComponent());
208 if (!option) {
209 return;
210 }
211
212 selectComponent_->RemoveSelectOption(option);
213 }
214
PrepareSpecializedComponent()215 void DOMSelect::PrepareSpecializedComponent()
216 {
217 if (selectComponent_) {
218 selectComponent_->SetTextDirection((IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR));
219 }
220 }
221
222 } // namespace OHOS::Ace::Framework
223