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