1 /*
2 * Copyright (c) 2021 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/input/dom_radio_util.h"
17
18 #include "frameworks/bridge/js_frontend/js_frontend.h"
19
20 namespace OHOS::Ace::Framework {
21 namespace {
22
GetRadioGroups(const DOMNode & node)23 std::shared_ptr<JsPageRadioGroups> GetRadioGroups(const DOMNode& node)
24 {
25 auto context = node.GetPipelineContext().Upgrade();
26 if (!context) {
27 return nullptr;
28 }
29 auto frontend = context->GetFrontend();
30 if (!frontend) {
31 return nullptr;
32 }
33 auto page = frontend->GetPage(node.GetPageId());
34 if (!page) {
35 auto jsFrontend = AceType::DynamicCast<JsFrontend>(frontend);
36 if (!jsFrontend) {
37 return nullptr;
38 }
39 page = jsFrontend->GetCurrentReadyPage().Upgrade();
40 }
41 auto jsPage = AceType::DynamicCast<JsAcePage>(page);
42 if (!jsPage) {
43 return nullptr;
44 }
45 return jsPage->GetRadioGroups();
46 }
47
48 } // namespace
49
InitDefaultValue(const RefPtr<RadioComponent<std::string>> & component)50 void DOMRadioUtil::InitDefaultValue(const RefPtr<RadioComponent<std::string>>& component) {}
51
CreateComponentAndSetChildAttr(const std::map<std::string,std::string> & attrs,DOMInput & node)52 RefPtr<RadioComponent<std::string>> DOMRadioUtil::CreateComponentAndSetChildAttr(
53 const std::map<std::string, std::string>& attrs, DOMInput& node)
54 {
55 // get theme to create component
56 RefPtr<RadioTheme> theme = node.GetTheme<RadioTheme>();
57 RefPtr<RadioComponent<std::string>> component = AceType::MakeRefPtr<RadioComponent<std::string>>(theme);
58 // set default value
59 InitDefaultValue(component);
60 // set the default hot zone
61 auto pipelineContext = node.GetPipelineContext().Upgrade();
62 if (pipelineContext->UseLiteStyle()) {
63 component->SetHorizontalPadding(Dimension(0));
64 component->SetHotZoneVerticalPadding(Dimension(0));
65 }
66 auto boxComponent = node.GetBoxComponent();
67 if (LessOrEqual(node.GetWidth().Value(), 0.0)) {
68 if (theme == nullptr) {
69 return nullptr;
70 }
71 node.SetWidth(theme->GetWidth());
72 boxComponent->SetWidth(theme->GetWidth().Value(), theme->GetWidth().Unit());
73 }
74 if (LessOrEqual(node.GetHeight().Value(), 0.0)) {
75 if (theme == nullptr) {
76 return nullptr;
77 }
78 node.SetHeight(theme->GetHeight());
79 boxComponent->SetHeight(theme->GetHeight().Value(), theme->GetHeight().Unit());
80 }
81 auto diameter = boxComponent->GetHeightDimension() > boxComponent->GetWidthDimension()
82 ? boxComponent->GetWidthDimension()
83 : boxComponent->GetHeightDimension();
84 if (!boxComponent->GetBackDecoration()) {
85 RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
86 backDecoration->SetBorderRadius(Radius(diameter / 2.0));
87 boxComponent->SetBackDecoration(backDecoration);
88 }
89
90 SetChildAttr(node, component, attrs);
91
92 return component;
93 }
94
SetChildAttr(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component,const std::map<std::string,std::string> & attrs)95 void DOMRadioUtil::SetChildAttr(const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component,
96 const std::map<std::string, std::string>& attrs)
97 {
98 if (!component) {
99 return;
100 }
101 bool checked = false;
102 for (const auto& attr : attrs) {
103 if (attr.first == DOM_INPUT_CHECKED) {
104 checked = StringToBool(attr.second);
105 } else if (attr.first == DOM_INPUT_NAME) {
106 CheckRadioGroup(node, component, attr.second);
107 } else if (attr.first == DOM_DISABLED) {
108 component->SetDisabled(StringToBool(attr.second));
109 } else if (attr.first == DOM_INPUT_VALUE) {
110 component->SetValue(attr.second);
111 }
112 }
113 if (checked) {
114 component->SetGroupValue(component->GetValue());
115 component->SetOriginChecked(checked);
116 } else {
117 component->SetGroupValue("");
118 }
119 }
120
SetChildStyle(const RefPtr<BoxComponent> & boxComponent,const RefPtr<RadioComponent<std::string>> & component,const std::map<std::string,std::string> & styles)121 void DOMRadioUtil::SetChildStyle(const RefPtr<BoxComponent>& boxComponent,
122 const RefPtr<RadioComponent<std::string>>& component, const std::map<std::string, std::string>& styles)
123 {
124 if (!component) {
125 return;
126 }
127 // Padding is set in radio specially so that it can respond click event.
128 boxComponent->SetPadding(Edge());
129 for (const auto& style : styles) {
130 if (style.first == DOM_PADDING) {
131 Edge padding;
132 if (Edge::FromString(style.second, padding)) {
133 component->SetHorizontalPadding(padding.Left());
134 component->SetHotZoneVerticalPadding(padding.Top());
135 }
136 }
137 }
138 }
139
AddChildEvent(const RefPtr<RadioComponent<std::string>> & component,int32_t pageId,const std::string & nodeId,const std::vector<std::string> & events)140 void DOMRadioUtil::AddChildEvent(const RefPtr<RadioComponent<std::string>>& component, int32_t pageId,
141 const std::string& nodeId, const std::vector<std::string>& events)
142 {
143 if (!component) {
144 return;
145 }
146 for (const auto& event : events) {
147 if (event == DOM_CHANGE) {
148 component->SetChangeEvent(EventMarker(nodeId, event, pageId));
149 } else if (event == DOM_CLICK) {
150 EventMarker eventMarker(nodeId, event, pageId);
151 eventMarker.SetCatchMode(false);
152 component->SetClickEvent(eventMarker);
153 } else if (event == DOM_CATCH_BUBBLE_CLICK) {
154 EventMarker eventMarker(nodeId, event, pageId);
155 eventMarker.SetCatchMode(true);
156 component->SetClickEvent(eventMarker);
157 }
158 }
159 }
160
RemoveRadioComponent(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component)161 void DOMRadioUtil::RemoveRadioComponent(const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component)
162 {
163 if (!component) {
164 return;
165 }
166 auto radioGroups = GetRadioGroups(node);
167 if (radioGroups == nullptr) {
168 return;
169 }
170
171 auto radioGroupIter = (*radioGroups).find(component->GetGroupName());
172 if (radioGroupIter != (*radioGroups).end()) {
173 radioGroupIter->second.RemoveRadio(component);
174 if (radioGroupIter->second.IsEmpty()) {
175 (*radioGroups).erase(radioGroupIter);
176 }
177 }
178 }
179
CheckRadioGroup(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component,const std::string & name)180 void DOMRadioUtil::CheckRadioGroup(
181 const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component, const std::string& name)
182 {
183 auto radioGroups = GetRadioGroups(node);
184 if (radioGroups == nullptr) {
185 return;
186 }
187 const auto& groupName = component->GetGroupName();
188 if (!groupName.empty()) {
189 if (groupName == name) {
190 return;
191 }
192 auto& oldRadioGroup = (*radioGroups)[groupName];
193 oldRadioGroup.RemoveRadio(component);
194 if (oldRadioGroup.IsEmpty()) {
195 (*radioGroups).erase(groupName);
196 }
197 }
198 component->SetGroupName(name);
199 auto& radioGroup = (*radioGroups)[name];
200 radioGroup.AddRadio(component);
201 }
202
203 } // namespace OHOS::Ace::Framework
204