1 /*
2  * Copyright (c) 2023 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 #include "core/interfaces/native/node/radio_modifier.h"
16 
17 #include <string>
18 
19 #include "core/components/checkable/checkable_theme.h"
20 #include "core/components/common/layout/constants.h"
21 #include "core/components/theme/theme_manager.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/base/view_abstract.h"
24 #include "core/components_ng/pattern/radio/radio_model_ng.h"
25 #include "core/pipeline/base/element_register.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 
28 
29 namespace OHOS::Ace::NG {
30 namespace {
31 constexpr bool DEFAULT_CHECKED = false;
32 const int32_t ERROR_INT_CODE = -1;
33 std::string g_radioStrValue;
34 
SetRadioChecked(ArkUINodeHandle node,ArkUI_Bool isCheck)35 void SetRadioChecked(ArkUINodeHandle node, ArkUI_Bool isCheck)
36 {
37     auto* frameNode = reinterpret_cast<FrameNode*>(node);
38     CHECK_NULL_VOID(frameNode);
39     RadioModelNG::SetChecked(frameNode, isCheck);
40 }
41 
ResetRadioChecked(ArkUINodeHandle node)42 void ResetRadioChecked(ArkUINodeHandle node)
43 {
44     auto* frameNode = reinterpret_cast<FrameNode*>(node);
45     CHECK_NULL_VOID(frameNode);
46     RadioModelNG::SetChecked(frameNode, DEFAULT_CHECKED);
47 }
48 
SetRadioStyle(ArkUINodeHandle node,ArkUI_Uint32 checkedBackgroundColor,ArkUI_Uint32 uncheckedBorderColor,ArkUI_Uint32 indicatorColor)49 void SetRadioStyle(ArkUINodeHandle node, ArkUI_Uint32 checkedBackgroundColor, ArkUI_Uint32 uncheckedBorderColor,
50     ArkUI_Uint32 indicatorColor)
51 {
52     auto* frameNode = reinterpret_cast<FrameNode*>(node);
53     CHECK_NULL_VOID(frameNode);
54 
55     RadioModelNG::SetCheckedBackgroundColor(frameNode, Color(checkedBackgroundColor));
56     RadioModelNG::SetUncheckedBorderColor(frameNode, Color(uncheckedBorderColor));
57     RadioModelNG::SetIndicatorColor(frameNode, Color(indicatorColor));
58 }
59 
ResetRadioStyle(ArkUINodeHandle node)60 void ResetRadioStyle(ArkUINodeHandle node)
61 {
62     auto* frameNode = reinterpret_cast<FrameNode*>(node);
63     CHECK_NULL_VOID(frameNode);
64 
65     auto context = frameNode->GetContext();
66     CHECK_NULL_VOID(context);
67     auto themeManager = context->GetThemeManager();
68     CHECK_NULL_VOID(themeManager);
69     auto theme = themeManager->GetTheme<RadioTheme>();
70     CHECK_NULL_VOID(theme);
71 
72     RadioModelNG::SetCheckedBackgroundColor(frameNode, theme->GetActiveColor());
73     RadioModelNG::SetUncheckedBorderColor(frameNode, theme->GetInactiveColor());
74     RadioModelNG::SetIndicatorColor(frameNode, theme->GetPointColor());
75 }
76 
SetRadioWidth(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit,ArkUI_CharPtr calcValue)77 void SetRadioWidth(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit, ArkUI_CharPtr calcValue)
78 {
79     auto* frameNode = reinterpret_cast<FrameNode*>(node);
80     CHECK_NULL_VOID(frameNode);
81     auto unitEnum = static_cast<OHOS::Ace::DimensionUnit>(unit);
82     if (unitEnum == DimensionUnit::CALC) {
83         ViewAbstract::SetWidth(frameNode, CalcLength(CalcLength(std::string(calcValue))));
84     } else {
85         ViewAbstract::SetWidth(frameNode, CalcLength(value, unitEnum));
86     }
87 }
88 
ResetRadioWidth(ArkUINodeHandle node)89 void ResetRadioWidth(ArkUINodeHandle node)
90 {
91     auto* frameNode = reinterpret_cast<FrameNode*>(node);
92     CHECK_NULL_VOID(frameNode);
93     ViewAbstract::ClearWidthOrHeight(frameNode, true);
94 }
95 
SetRadioHeight(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit,ArkUI_CharPtr calcValue)96 void SetRadioHeight(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit, ArkUI_CharPtr calcValue)
97 {
98     auto* frameNode = reinterpret_cast<FrameNode*>(node);
99     CHECK_NULL_VOID(frameNode);
100     auto unitEnum = static_cast<OHOS::Ace::DimensionUnit>(unit);
101     if (unitEnum == DimensionUnit::CALC) {
102         ViewAbstract::SetHeight(frameNode, CalcLength(CalcLength(std::string(calcValue))));
103     } else {
104         ViewAbstract::SetHeight(frameNode, CalcLength(value, unitEnum));
105     }
106 }
107 
ResetRadioHeight(ArkUINodeHandle node)108 void ResetRadioHeight(ArkUINodeHandle node)
109 {
110     auto* frameNode = reinterpret_cast<FrameNode*>(node);
111     CHECK_NULL_VOID(frameNode);
112     ViewAbstract::ClearWidthOrHeight(frameNode, false);
113 }
114 
SetRadioSize(ArkUINodeHandle node,ArkUI_Float32 widthValue,ArkUI_Int32 widthUnit,ArkUI_Float32 heightValue,ArkUI_Int32 heightUnit)115 void SetRadioSize(ArkUINodeHandle node, ArkUI_Float32 widthValue, ArkUI_Int32 widthUnit, ArkUI_Float32 heightValue,
116     ArkUI_Int32 heightUnit)
117 {
118     auto* frameNode = reinterpret_cast<FrameNode*>(node);
119     CHECK_NULL_VOID(frameNode);
120     RadioModelNG::SetWidth(frameNode, Dimension(widthValue, static_cast<OHOS::Ace::DimensionUnit>(widthUnit)));
121     RadioModelNG::SetHeight(frameNode, Dimension(heightValue, static_cast<OHOS::Ace::DimensionUnit>(heightUnit)));
122 }
123 
ResetRadioSize(ArkUINodeHandle node)124 void ResetRadioSize(ArkUINodeHandle node)
125 {
126     auto* frameNode = reinterpret_cast<FrameNode*>(node);
127     CHECK_NULL_VOID(frameNode);
128     auto pipeline = PipelineBase::GetCurrentContext();
129     CHECK_NULL_VOID(pipeline);
130     auto radioTheme = pipeline->GetTheme<RadioTheme>();
131     CHECK_NULL_VOID(radioTheme);
132     auto defaultWidth = radioTheme->GetDefaultWidth();
133     auto horizontalPadding = radioTheme->GetHotZoneHorizontalPadding();
134     auto width = defaultWidth - horizontalPadding * 2; //2 is Calculate the parameters of the formula
135 
136     auto defaultHeight = radioTheme->GetDefaultHeight();
137     auto verticalPadding = radioTheme->GetHotZoneVerticalPadding();
138     auto height = defaultHeight - verticalPadding * 2; //2 is Calculate the parameters of the formula
139     RadioModelNG::SetWidth(frameNode, width);
140     RadioModelNG::SetHeight(frameNode, height);
141 }
142 
SetRadioHoverEffect(ArkUINodeHandle node,ArkUI_Int32 hoverEffectValue)143 void SetRadioHoverEffect(ArkUINodeHandle node, ArkUI_Int32 hoverEffectValue)
144 {
145     auto* frameNode = reinterpret_cast<FrameNode*>(node);
146     CHECK_NULL_VOID(frameNode);
147     OHOS::Ace::HoverEffectType hoverEffect = OHOS::Ace::HoverEffectType::AUTO;
148     hoverEffect = static_cast<OHOS::Ace::HoverEffectType>(hoverEffectValue);
149     RadioModelNG::SetHoverEffect(frameNode, hoverEffect);
150 }
151 
ResetRadioHoverEffect(ArkUINodeHandle node)152 void ResetRadioHoverEffect(ArkUINodeHandle node)
153 {
154     auto* frameNode = reinterpret_cast<FrameNode*>(node);
155     CHECK_NULL_VOID(frameNode);
156     RadioModelNG::SetHoverEffect(frameNode, OHOS::Ace::HoverEffectType::AUTO);
157 }
158 
SetRadioPadding(ArkUINodeHandle node,const struct ArkUISizeType * top,const struct ArkUISizeType * right,const struct ArkUISizeType * bottom,const struct ArkUISizeType * left)159 void SetRadioPadding(ArkUINodeHandle node, const struct ArkUISizeType* top, const struct ArkUISizeType* right,
160     const struct ArkUISizeType* bottom, const struct ArkUISizeType* left)
161 {
162     auto* frameNode = reinterpret_cast<FrameNode*>(node);
163     CHECK_NULL_VOID(frameNode);
164     CalcLength topDimen;
165     CalcLength rightDimen;
166     CalcLength bottomDimen;
167     CalcLength leftDimen;
168     if (top->string != nullptr) {
169         topDimen = CalcLength(top->string);
170     } else {
171         topDimen = CalcLength(top->value, static_cast<DimensionUnit>(top->unit));
172     }
173     if (right->string != nullptr) {
174         rightDimen = CalcLength(right->string);
175     } else {
176         rightDimen = CalcLength(right->value, static_cast<DimensionUnit>(right->unit));
177     }
178     if (bottom->string != nullptr) {
179         bottomDimen = CalcLength(bottom->string);
180     } else {
181         bottomDimen = CalcLength(bottom->value, static_cast<DimensionUnit>(bottom->unit));
182     }
183     if (left->string != nullptr) {
184         leftDimen = CalcLength(left->string);
185     } else {
186         leftDimen = CalcLength(left->value, static_cast<DimensionUnit>(left->unit));
187     }
188     NG::PaddingProperty paddings;
189     paddings.top = std::optional<CalcLength>(topDimen);
190     paddings.bottom = std::optional<CalcLength>(bottomDimen);
191     paddings.left = std::optional<CalcLength>(leftDimen);
192     paddings.right = std::optional<CalcLength>(rightDimen);
193     RadioModelNG::SetPadding(frameNode, paddings);
194 }
195 
ResetRadioPadding(ArkUINodeHandle node)196 void ResetRadioPadding(ArkUINodeHandle node)
197 {
198     auto* frameNode = reinterpret_cast<FrameNode*>(node);
199     CHECK_NULL_VOID(frameNode);
200     NG::PaddingProperty paddings;
201     paddings.top = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
202     paddings.bottom = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
203     paddings.left = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
204     paddings.right = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
205     RadioModelNG::SetPadding(frameNode, paddings);
206 }
207 
SetRadioResponseRegion(ArkUINodeHandle node,const ArkUI_Float32 * values,const ArkUI_Int32 * units,ArkUI_Uint32 length)208 void SetRadioResponseRegion(
209     ArkUINodeHandle node, const ArkUI_Float32* values, const ArkUI_Int32* units, ArkUI_Uint32 length)
210 {
211     auto* frameNode = reinterpret_cast<FrameNode*>(node);
212     CHECK_NULL_VOID(frameNode);
213     std::vector<DimensionRect> region;
214     for (uint32_t i = 0; i < length / 4; i++) { //4 is 4 different parameters
215         CalcDimension xDimen =
216             CalcDimension(values[i * 4 + 0], static_cast<DimensionUnit>(units[i * 4 + 0])); //4:parameters
217         CalcDimension yDimen =
218             CalcDimension(values[i * 4 + 1], static_cast<DimensionUnit>(units[i * 4 + 1])); //4:parameters
219         CalcDimension widthDimen =
220             CalcDimension(values[i * 4 + 2], static_cast<DimensionUnit>(units[i * 4 + 2])); //4:parameters, 2:width
221         CalcDimension heightDimen =
222             CalcDimension(values[i * 4 + 3], static_cast<DimensionUnit>(units[i * 4 + 3])); //4:parameters, 3:height
223         DimensionOffset offsetDimen(xDimen, yDimen);
224         DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
225         region.emplace_back(dimenRect);
226     }
227     RadioModelNG::SetResponseRegion(frameNode, region);
228 }
229 
ResetRadioResponseRegion(ArkUINodeHandle node)230 void ResetRadioResponseRegion(ArkUINodeHandle node)
231 {
232     auto* frameNode = reinterpret_cast<FrameNode*>(node);
233     CHECK_NULL_VOID(frameNode);
234     std::vector<DimensionRect> region;
235     CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
236     CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
237     CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
238     CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
239     DimensionOffset offsetDimen(xDimen, yDimen);
240     DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
241     region.emplace_back(dimenRect);
242     RadioModelNG::SetResponseRegion(frameNode, region);
243 }
244 
GetRadioChecked(ArkUINodeHandle node)245 ArkUI_Bool GetRadioChecked(ArkUINodeHandle node)
246 {
247     auto* frameNode = reinterpret_cast<FrameNode*>(node);
248     CHECK_NULL_RETURN(frameNode, ERROR_INT_CODE);
249     return static_cast<ArkUI_Bool>(RadioModelNG::GetChecked(frameNode));
250 }
251 
GetRadioStyle(ArkUINodeHandle node,ArkUIRadioStyleOption * options)252 void GetRadioStyle(ArkUINodeHandle node, ArkUIRadioStyleOption* options)
253 {
254     auto* frameNode = reinterpret_cast<FrameNode*>(node);
255     CHECK_NULL_VOID(frameNode);
256     options->checkedBackgroundColor = RadioModelNG::GetCheckedBackgroundColor(frameNode).GetValue();
257     options->uncheckedBorderColor = RadioModelNG::GetUncheckedBorderColor(frameNode).GetValue();
258     options->indicatorColor = RadioModelNG::GetIndicatorColor(frameNode).GetValue();
259 }
260 
SetRadioValue(ArkUINodeHandle node,ArkUI_CharPtr value)261 void SetRadioValue(ArkUINodeHandle node, ArkUI_CharPtr value)
262 {
263     auto* frameNode = reinterpret_cast<FrameNode*>(node);
264     CHECK_NULL_VOID(frameNode);
265     RadioModelNG::SetRadioValue(frameNode, std::string(value));
266 }
267 
ResetRadioValue(ArkUINodeHandle node)268 void ResetRadioValue(ArkUINodeHandle node)
269 {
270     auto* frameNode = reinterpret_cast<FrameNode*>(node);
271     CHECK_NULL_VOID(frameNode);
272     RadioModelNG::SetRadioValue(frameNode, "");
273 }
274 
GetSetRadioValue(ArkUINodeHandle node)275 ArkUI_CharPtr GetSetRadioValue(ArkUINodeHandle node)
276 {
277     auto* frameNode = reinterpret_cast<FrameNode*>(node);
278     CHECK_NULL_RETURN(frameNode, nullptr);
279     g_radioStrValue = RadioModelNG::GetRadioValue(frameNode);
280     return g_radioStrValue.c_str();
281 }
282 
SetRadioGroup(ArkUINodeHandle node,ArkUI_CharPtr value)283 void SetRadioGroup(ArkUINodeHandle node, ArkUI_CharPtr value)
284 {
285     auto* frameNode = reinterpret_cast<FrameNode*>(node);
286     CHECK_NULL_VOID(frameNode);
287     RadioModelNG::SetRadioGroup(frameNode, std::string(value));
288 }
289 
ResetRadioGroup(ArkUINodeHandle node)290 void ResetRadioGroup(ArkUINodeHandle node)
291 {
292     auto* frameNode = reinterpret_cast<FrameNode*>(node);
293     CHECK_NULL_VOID(frameNode);
294     RadioModelNG::SetRadioGroup(frameNode, "");
295 }
296 
GetRadioGroup(ArkUINodeHandle node)297 ArkUI_CharPtr GetRadioGroup(ArkUINodeHandle node)
298 {
299     auto* frameNode = reinterpret_cast<FrameNode*>(node);
300     CHECK_NULL_RETURN(frameNode, nullptr);
301     g_radioStrValue = RadioModelNG::GetRadioGroup(frameNode);
302     return g_radioStrValue.c_str();
303 }
304 } // namespace
305 
306 namespace NodeModifier {
GetRadioModifier()307 const ArkUIRadioModifier* GetRadioModifier()
308 {
309     static const ArkUIRadioModifier modifier = { SetRadioChecked, ResetRadioChecked, SetRadioStyle, ResetRadioStyle,
310         SetRadioWidth, ResetRadioWidth, SetRadioHeight, ResetRadioHeight, SetRadioSize, ResetRadioSize,
311         SetRadioHoverEffect, ResetRadioHoverEffect, SetRadioPadding, ResetRadioPadding, SetRadioResponseRegion,
312         ResetRadioResponseRegion, GetRadioChecked, GetRadioStyle, SetRadioValue, ResetRadioValue, GetSetRadioValue,
313         SetRadioGroup, ResetRadioGroup, GetRadioGroup };
314 
315     return &modifier;
316 }
317 
GetCJUIRadioModifier()318 const CJUIRadioModifier* GetCJUIRadioModifier()
319 {
320     static const CJUIRadioModifier modifier = { SetRadioChecked, ResetRadioChecked, SetRadioStyle, ResetRadioStyle,
321         SetRadioWidth, ResetRadioWidth, SetRadioHeight, ResetRadioHeight, SetRadioSize, ResetRadioSize,
322         SetRadioHoverEffect, ResetRadioHoverEffect, SetRadioPadding, ResetRadioPadding, SetRadioResponseRegion,
323         ResetRadioResponseRegion, GetRadioChecked, GetRadioStyle, SetRadioValue, ResetRadioValue, GetSetRadioValue,
324         SetRadioGroup, ResetRadioGroup, GetRadioGroup };
325 
326     return &modifier;
327 }
328 
SetOnRadioChange(ArkUINodeHandle node,void * extraParam)329 void SetOnRadioChange(ArkUINodeHandle node, void* extraParam)
330 {
331     auto* frameNode = reinterpret_cast<FrameNode*>(node);
332     CHECK_NULL_VOID(frameNode);
333     auto onChange = [node, extraParam](const bool value) {
334         ArkUINodeEvent event;
335         event.kind = COMPONENT_ASYNC_EVENT;
336         event.extraParam = reinterpret_cast<intptr_t>(extraParam);
337         event.componentAsyncEvent.subKind = ON_RADIO_CHANGE;
338         event.componentAsyncEvent.data[0].i32 = static_cast<int>(value);
339         SendArkUIAsyncEvent(&event);
340     };
341     RadioModelNG::SetOnChange(frameNode, std::move(onChange));
342 }
343 } // namespace NodeModifier
344 } // namespace OHOS::Ace::NG