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(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
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 selectComponent_->InitTheme(GetThemeManager());
54 theme_ = GetTheme<SelectTheme>();
55 if (theme_ && selectComponent_) {
56 selectComponent_->SetClickedColor(theme_->GetClickedColor());
57 selectComponent_->SetDisabledColor(theme_->GetDisabledColor());
58 selectComponent_->SetSelectedColor(theme_->GetSelectedColor());
59 selectComponent_->SetOptionSize(theme_->GetOptionSize());
60 selectComponent_->SetRRectSize(theme_->GetRRectSize());
61 selectComponent_->SetPopupBorderWidth(theme_->GetPopupBorderWidth());
62 selectComponent_->SetPopupShadowWidth(theme_->GetPopupShadowWidth());
63 selectComponent_->SetFontFamily(theme_->GetFontFamily());
64 selectComponent_->SetFontSize(theme_->GetFontSize());
65 selectComponent_->SetAllowScale(theme_->IsAllowScale());
66 selectComponent_->SetTextColor(theme_->GetFontColor());
67 selectComponent_->SetFontWeight(FontWeight::W500);
68 selectComponent_->SetTextDecoration(theme_->GetTextDecoration());
69 selectComponent_->SetBackgroundColor(Color::TRANSPARENT);
70 }
71 }
72
UpdateBoxSize(const CalcDimension & width,const CalcDimension & height)73 void DOMSelect::UpdateBoxSize(const CalcDimension& width, const CalcDimension& height)
74 {
75 if (!selectComponent_) {
76 return;
77 }
78
79 if (width.Unit() != DimensionUnit::PERCENT && height.Unit() != DimensionUnit::PERCENT) {
80 selectComponent_->SetInnerSize(width, height);
81 return;
82 }
83
84 if (width.Unit() == DimensionUnit::PERCENT && height.Unit() == DimensionUnit::PERCENT) {
85 DOMNode::UpdateBoxSize(width, height);
86 selectComponent_->SetInnerSize(100.0_pct, 100.0_pct);
87 return;
88 }
89
90 if (width.Unit() == DimensionUnit::PERCENT) {
91 DOMNode::UpdateBoxSize(width, height);
92 selectComponent_->SetInnerSize(100.0_pct, height);
93 return;
94 }
95
96 DOMNode::UpdateBoxSize(width, height);
97 selectComponent_->SetInnerSize(100.0_pct, 100.0_pct);
98 }
99
UpdateBoxPadding(const Edge & padding)100 void DOMSelect::UpdateBoxPadding(const Edge& padding)
101 {
102 if (!selectComponent_) {
103 return;
104 }
105
106 selectComponent_->SetInnerPadding(padding);
107 }
108
UpdateBoxBorder(const Border & border)109 void DOMSelect::UpdateBoxBorder(const Border& border)
110 {
111 if (!selectComponent_) {
112 return;
113 }
114
115 selectComponent_->SetInnerBorder(border);
116 }
117
AddSpecializedEvent(int32_t pageId,const std::string & event)118 bool DOMSelect::AddSpecializedEvent(int32_t pageId, const std::string& event)
119 {
120 if (event == DOM_CHANGE) {
121 onChanged_ = EventMarker(GetNodeIdForEvent(), event, pageId);
122 selectComponent_->SetOnChanged(onChanged_);
123 return true;
124 }
125 return false;
126 }
127
SetSpecializedStyle(const std::pair<std::string,std::string> & style)128 bool DOMSelect::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
129 {
130 if (IsParentNavigation()) {
131 // not support style setting for navigation.
132 return true;
133 }
134
135 static const LinearMapNode<void (*)(const std::string&, const DOMSelect&, SelectComponent&)>
136 selectStyleOperators[] = {
137 { DOM_TEXT_ALLOW_SCALE, [](const std::string& val, const DOMSelect& node,
138 SelectComponent& select) { select.SetAllowScale(StringToBool(val)); } },
139 { DOM_BACKGROUND_COLOR, [](const std::string& val, const DOMSelect& node,
140 SelectComponent& select) { select.SetBackgroundColor(node.ParseColor(val)); } },
141 { DOM_TEXT_COLOR, [](const std::string& val, const DOMSelect& node,
142 SelectComponent& select) { select.SetTextColor(node.ParseColor(val)); } },
143 { DOM_TEXT_FONT_FAMILY, [](const std::string& val, const DOMSelect& node,
144 SelectComponent& select) { select.SetFontFamily(val); } },
145 { DOM_TEXT_FONT_SIZE,
146 [](const std::string& val, const DOMSelect& node, SelectComponent& select) {
147 select.SetFontSize(node.ParseDimension(val));
148 select.SetIsFontSetFlag(true);
149 } },
150 { DOM_TEXT_FONT_WEIGHT, [](const std::string& val, const DOMSelect& node,
151 SelectComponent& select) { select.SetFontWeight(ConvertStrToFontWeight(val)); } },
152 { DOM_TEXT_DECORATION,
153 [](const std::string& val, const DOMSelect& node, SelectComponent& select) {
154 select.SetTextDecoration(ConvertStrToTextDecoration(val));
155 } },
156 };
157 auto operatorIter =
158 BinarySearchFindIndex(selectStyleOperators, ArraySize(selectStyleOperators), style.first.c_str());
159 if (operatorIter != -1) {
160 selectStyleOperators[operatorIter].value(style.second, *this, *selectComponent_);
161 return true;
162 }
163 return false;
164 }
165
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)166 void DOMSelect::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
167 {
168 if (!child || child->GetTag() != DOM_NODE_TAG_OPTION) {
169 LOGE("DOMSelect child is not correct");
170 return;
171 }
172
173 auto option = AceType::DynamicCast<DOMOption>(child);
174 if (option) {
175 auto optionComponent = AceType::DynamicCast<OptionComponent>(option->GetSpecializedComponent());
176 if (!optionComponent) {
177 return;
178 }
179 if (!selectComponent_->GetSelectOptionCount() || optionComponent->GetSelected()) {
180 auto text = optionComponent->GetText();
181 if (text) {
182 tipText_->SetData(text->GetData());
183 } else {
184 LOGE("text of option component is null.");
185 tipText_->SetData("");
186 }
187 }
188 if (slot < 0) {
189 selectComponent_->AppendSelectOption(optionComponent);
190 } else {
191 selectComponent_->InsertSelectOption(optionComponent, static_cast<uint32_t>(slot));
192 }
193 LOGD("DOMSelect %{public}s, appendChild %{public}s", GetTag().c_str(), child->GetTag().c_str());
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