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