• 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         node.SetWidth(theme->GetWidth());
76         boxComponent->SetWidth(theme->GetWidth().Value(), theme->GetWidth().Unit());
77     }
78     if (LessOrEqual(node.GetHeight().Value(), 0.0)) {
79         node.SetHeight(theme->GetHeight());
80         boxComponent->SetHeight(theme->GetHeight().Value(), theme->GetHeight().Unit());
81     }
82     auto diameter = boxComponent->GetHeightDimension() > boxComponent->GetWidthDimension()
83                         ? boxComponent->GetWidthDimension()
84                         : boxComponent->GetHeightDimension();
85     if (!boxComponent->GetBackDecoration()) {
86         RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
87         backDecoration->SetBorderRadius(Radius(diameter / 2.0));
88         boxComponent->SetBackDecoration(backDecoration);
89     }
90 
91     SetChildAttr(node, component, attrs);
92 
93     return component;
94 }
95 
SetChildAttr(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component,const std::map<std::string,std::string> & attrs)96 void DOMRadioUtil::SetChildAttr(const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component,
97     const std::map<std::string, std::string>& attrs)
98 {
99     if (!component) {
100         LOGE("fail to set child attr due to radio component is null");
101         return;
102     }
103     bool checked = false;
104     for (const auto& attr : attrs) {
105         if (attr.first == DOM_INPUT_CHECKED) {
106             checked = StringToBool(attr.second);
107         } else if (attr.first == DOM_INPUT_NAME) {
108             CheckRadioGroup(node, component, attr.second);
109         } else if (attr.first == DOM_DISABLED) {
110             component->SetDisabled(StringToBool(attr.second));
111         } else if (attr.first == DOM_INPUT_VALUE) {
112             component->SetValue(attr.second);
113         }
114     }
115     if (checked) {
116         component->SetGroupValue(component->GetValue());
117         component->SetOriginChecked(checked);
118     } else {
119         component->SetGroupValue("");
120     }
121 }
122 
SetChildStyle(const RefPtr<BoxComponent> & boxComponent,const RefPtr<RadioComponent<std::string>> & component,const std::map<std::string,std::string> & styles)123 void DOMRadioUtil::SetChildStyle(const RefPtr<BoxComponent>& boxComponent,
124     const RefPtr<RadioComponent<std::string>>& component, const std::map<std::string, std::string>& styles)
125 {
126     if (!component) {
127         LOGE("fail to set child attr due to radio component is null");
128         return;
129     }
130     // Padding is set in radio specially so that it can respond click event.
131     boxComponent->SetPadding(Edge());
132     for (const auto& style : styles) {
133         if (style.first == DOM_PADDING) {
134             Edge padding;
135             if (Edge::FromString(style.second, padding)) {
136                 component->SetHorizontalPadding(padding.Left());
137                 component->SetHotZoneVerticalPadding(padding.Top());
138             }
139         }
140     }
141 }
142 
AddChildEvent(const RefPtr<RadioComponent<std::string>> & component,int32_t pageId,const std::string & nodeId,const std::vector<std::string> & events)143 void DOMRadioUtil::AddChildEvent(const RefPtr<RadioComponent<std::string>>& component, int32_t pageId,
144     const std::string& nodeId, const std::vector<std::string>& events)
145 {
146     if (!component) {
147         LOGE("fail to add child event due to radio component is null");
148         return;
149     }
150     for (const auto& event : events) {
151         if (event == DOM_CHANGE) {
152             component->SetChangeEvent(EventMarker(nodeId, event, pageId));
153         } else if (event == DOM_CLICK) {
154             EventMarker eventMarker(nodeId, event, pageId);
155             eventMarker.SetCatchMode(false);
156             component->SetClickEvent(eventMarker);
157         } else if (event == DOM_CATCH_BUBBLE_CLICK) {
158             EventMarker eventMarker(nodeId, event, pageId);
159             eventMarker.SetCatchMode(true);
160             component->SetClickEvent(eventMarker);
161         }
162     }
163 }
164 
RemoveRadioComponent(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component)165 void DOMRadioUtil::RemoveRadioComponent(const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component)
166 {
167     if (!component) {
168         return;
169     }
170     auto radioGroups = GetRadioGroups(node);
171     if (radioGroups == nullptr) {
172         return;
173     }
174 
175     auto radioGroupIter = (*radioGroups).find(component->GetGroupName());
176     if (radioGroupIter != (*radioGroups).end()) {
177         radioGroupIter->second.RemoveRadio(component);
178         if (radioGroupIter->second.IsEmpty()) {
179             (*radioGroups).erase(radioGroupIter);
180         }
181     }
182 }
183 
CheckRadioGroup(const DOMInput & node,const RefPtr<RadioComponent<std::string>> & component,const std::string & name)184 void DOMRadioUtil::CheckRadioGroup(
185     const DOMInput& node, const RefPtr<RadioComponent<std::string>>& component, const std::string& name)
186 {
187     auto radioGroups = GetRadioGroups(node);
188     if (radioGroups == nullptr) {
189         return;
190     }
191     const auto& groupName = component->GetGroupName();
192     if (!groupName.empty()) {
193         if (groupName == name) {
194             return;
195         }
196         auto& oldRadioGroup = (*radioGroups)[groupName];
197         oldRadioGroup.RemoveRadio(component);
198         if (oldRadioGroup.IsEmpty()) {
199             (*radioGroups).erase(groupName);
200         }
201     }
202     component->SetGroupName(name);
203     auto& radioGroup = (*radioGroups)[name];
204     radioGroup.AddRadio(component);
205 }
206 
207 } // namespace OHOS::Ace::Framework
208