1 /*
2  * Copyright (c) 2024 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 "node_toggle_modifier.h"
16 
17 #include "core/components/checkable/checkable_theme.h"
18 #include "core/components/common/layout/constants.h"
19 #include "core/components_ng/base/frame_node.h"
20 #include "core/components_ng/pattern/toggle/toggle_model_ng.h"
21 #include "core/interfaces/arkoala/arkoala_api.h"
22 #include "core/interfaces/native/node/node_api.h"
23 #include "core/pipeline/base/element_register.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 
26 namespace OHOS::Ace::NG {
27 const int32_t ERROR_UINT_CODE = -1;
28 namespace {
29 constexpr uint32_t RESPONSE_REGION_STEP = 4;
30 constexpr uint32_t OFFSET_0 = 0;
31 constexpr uint32_t OFFSET_1 = 1;
32 constexpr uint32_t OFFSET_2 = 2;
33 constexpr uint32_t OFFSET_3 = 3;
34 constexpr uint32_t INDEX_DIMENSION_TOP_0 = 0;
35 constexpr uint32_t INDEX_DIMENSION_RIGHT_1 = 1;
36 constexpr uint32_t INDEX_DIMENSION_BOTTOM_2 = 2;
37 constexpr uint32_t INDEX_DIMENSION_LEFT_3 = 3;
38 constexpr uint32_t DIMENSION_STEP = 3;
39 
SetToggleDimension(const ArkUI_Float32 * dimensionArray,ArkUI_Uint32 offset,const size_t dataCount,std::optional<CalcDimension> & optDimension)40 bool SetToggleDimension(
41     const ArkUI_Float32* dimensionArray, ArkUI_Uint32 offset, const size_t dataCount,
42     std::optional<CalcDimension>& optDimension)
43 {
44     CHECK_NULL_RETURN(dimensionArray, false);
45     auto hasValue = dimensionArray[offset];
46     if (!static_cast<bool>(hasValue)) {
47         return false;
48     }
49     uint32_t valueIndex = offset + 1;
50     uint32_t unitIndex = offset + 2;
51     if (unitIndex >= dataCount) {
52         return false;
53     }
54     auto value = dimensionArray[valueIndex];
55     auto unit = dimensionArray[unitIndex];
56     DimensionUnit unitValue = static_cast<DimensionUnit>(unit);
57     CalcDimension dimensionValue = CalcDimension(value, unitValue);
58     optDimension = dimensionValue;
59     return true;
60 }
61 
SetToggleSelectedColor(ArkUINodeHandle node,ArkUI_Uint32 selectedColor)62 void SetToggleSelectedColor(ArkUINodeHandle node, ArkUI_Uint32 selectedColor)
63 {
64     auto* frameNode = reinterpret_cast<FrameNode*>(node);
65     CHECK_NULL_VOID(frameNode);
66     ToggleModelNG::SetSelectedColor(frameNode, Color(selectedColor));
67 }
68 
ResetToggleSelectedColor(ArkUINodeHandle node)69 void ResetToggleSelectedColor(ArkUINodeHandle node)
70 {
71     auto* frameNode = reinterpret_cast<FrameNode*>(node);
72     CHECK_NULL_VOID(frameNode);
73     std::optional<Color> selectedColor;
74     ToggleModelNG::SetSelectedColor(frameNode, selectedColor);
75 }
76 
SetToggleSwitchPointColor(ArkUINodeHandle node,ArkUI_Uint32 switchPointColor)77 void SetToggleSwitchPointColor(ArkUINodeHandle node, ArkUI_Uint32 switchPointColor)
78 {
79     auto* frameNode = reinterpret_cast<FrameNode*>(node);
80     CHECK_NULL_VOID(frameNode);
81     ToggleModelNG::SetSwitchPointColor(frameNode, Color(switchPointColor));
82 }
83 
ResetToggleSwitchPointColor(ArkUINodeHandle node)84 void ResetToggleSwitchPointColor(ArkUINodeHandle node)
85 {
86     auto* frameNode = reinterpret_cast<FrameNode*>(node);
87     CHECK_NULL_VOID(frameNode);
88     auto context = frameNode->GetContext();
89     CHECK_NULL_VOID(context);
90     auto themeManager = context->GetThemeManager();
91     CHECK_NULL_VOID(themeManager);
92     auto theme = themeManager->GetTheme<SwitchTheme>();
93     Color color;
94     if (theme) {
95         color = theme->GetPointColor();
96     }
97     ToggleModelNG::SetSwitchPointColor(frameNode, Color(color));
98 }
99 
GetToggleSelectedColor(ArkUINodeHandle node)100 ArkUI_Uint32 GetToggleSelectedColor(ArkUINodeHandle node)
101 {
102     auto* frameNode = reinterpret_cast<FrameNode*>(node);
103     CHECK_NULL_RETURN(frameNode, ERROR_UINT_CODE);
104     return ToggleModelNG::GetSelectedColor(frameNode).GetValue();
105 }
106 
GetToggleSwitchPointColor(ArkUINodeHandle node)107 ArkUI_Uint32 GetToggleSwitchPointColor(ArkUINodeHandle node)
108 {
109     auto* frameNode = reinterpret_cast<FrameNode*>(node);
110     CHECK_NULL_RETURN(frameNode, ERROR_UINT_CODE);
111     return ToggleModelNG::GetSwitchPointColor(frameNode).GetValue();
112 }
113 
SetToggleHeight(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)114 void SetToggleHeight(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
115 {
116     auto* frameNode = reinterpret_cast<FrameNode*>(node);
117     CHECK_NULL_VOID(frameNode);
118     DimensionUnit unitValue = static_cast<DimensionUnit>(unit);
119     CalcDimension dimensionValue = CalcDimension(value, unitValue);
120     ToggleModelNG::SetHeight(frameNode, dimensionValue);
121 }
122 
ResetToggleHeight(ArkUINodeHandle node)123 void ResetToggleHeight(ArkUINodeHandle node)
124 {
125     auto* frameNode = reinterpret_cast<FrameNode*>(node);
126     CHECK_NULL_VOID(frameNode);
127     auto switchTheme = GetTheme<SwitchTheme>();
128     CHECK_NULL_VOID(switchTheme);
129     auto defaultHeight = switchTheme->GetHeight();
130     auto verticalPadding = switchTheme->GetHotZoneVerticalPadding();
131     auto height = defaultHeight - verticalPadding * 2;
132     CalcDimension value(height);
133     ToggleModelNG::SetHeight(frameNode, value);
134 }
135 
SetToggleResponseRegion(ArkUINodeHandle node,const ArkUI_Float32 * values,const ArkUI_Int32 * units,ArkUI_Uint32 length)136 void SetToggleResponseRegion(ArkUINodeHandle node, const ArkUI_Float32* values,
137     const ArkUI_Int32* units, ArkUI_Uint32 length)
138 {
139     CHECK_NULL_VOID(values);
140     CHECK_NULL_VOID(units);
141     auto* frameNode = reinterpret_cast<FrameNode*>(node);
142     CHECK_NULL_VOID(frameNode);
143     std::vector<DimensionRect> region;
144     for (uint32_t i = 0; i + OFFSET_3 < length; i = i + RESPONSE_REGION_STEP) {
145         CalcDimension xDimen = CalcDimension(values[i + OFFSET_0], static_cast<DimensionUnit>(units[i + OFFSET_0]));
146         CalcDimension yDimen = CalcDimension(values[i + OFFSET_1], static_cast<DimensionUnit>(units[i + OFFSET_1]));
147         CalcDimension widthDimen = CalcDimension(values[i + OFFSET_2], static_cast<DimensionUnit>(units[i + OFFSET_2]));
148         CalcDimension heightDimen =
149             CalcDimension(values[i + OFFSET_3], static_cast<DimensionUnit>(units[i + OFFSET_3]));
150         DimensionOffset offsetDimen(xDimen, yDimen);
151         DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
152         region.emplace_back(dimenRect);
153     }
154     ToggleModelNG::SetResponseRegion(frameNode, region);
155 }
156 
ResetToggleResponseRegion(ArkUINodeHandle node)157 void ResetToggleResponseRegion(ArkUINodeHandle node)
158 {
159     auto* frameNode = reinterpret_cast<FrameNode*>(node);
160     CHECK_NULL_VOID(frameNode);
161     std::vector<DimensionRect> region;
162     CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
163     CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
164     CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
165     CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
166     DimensionOffset offsetDimen(xDimen, yDimen);
167     DimensionRect dimenRect(widthDimen, heightDimen, offsetDimen);
168     region.emplace_back(dimenRect);
169     ToggleModelNG::SetResponseRegion(frameNode, region);
170 }
171 
SetTogglePadding(ArkUINodeHandle node,const ArkUI_Float32 * values,const ArkUI_Uint32 length)172 void SetTogglePadding(ArkUINodeHandle node, const ArkUI_Float32* values, const ArkUI_Uint32 length)
173 {
174     auto* frameNode = reinterpret_cast<FrameNode*>(node);
175     CHECK_NULL_VOID(frameNode);
176     CHECK_NULL_VOID(values);
177     CalcLength topDimen;
178     CalcLength rightDimen;
179     CalcLength bottomDimen;
180     CalcLength leftDimen;
181     uint32_t step = DIMENSION_STEP;
182     uint32_t topIndex = INDEX_DIMENSION_TOP_0;
183     std::optional<CalcDimension> topOptional = std::nullopt;
184     if (SetToggleDimension(values, topIndex, length, topOptional)) {
185         topDimen = CalcLength(
186             CalcDimension(topOptional.value().Value(), static_cast<DimensionUnit>(topOptional.value().Unit())));
187     }
188     uint32_t rightIndex = INDEX_DIMENSION_RIGHT_1 * step;
189     std::optional<CalcDimension> rightOptional = std::nullopt;
190     if (SetToggleDimension(values, rightIndex, length, rightOptional)) {
191         rightDimen = CalcLength(
192             CalcDimension(rightOptional.value().Value(), static_cast<DimensionUnit>(rightOptional.value().Unit())));
193     }
194     uint32_t bottomIndex = INDEX_DIMENSION_BOTTOM_2 * step;
195     std::optional<CalcDimension> bottomOptional = std::nullopt;
196     if (SetToggleDimension(values, bottomIndex, length, bottomOptional)) {
197         bottomDimen = CalcLength(
198             CalcDimension(bottomOptional.value().Value(), static_cast<DimensionUnit>(bottomOptional.value().Unit())));
199     }
200     uint32_t leftIndex = INDEX_DIMENSION_LEFT_3 * step;
201     std::optional<CalcDimension> leftOptional = std::nullopt;
202     if (SetToggleDimension(values, leftIndex, length, leftOptional)) {
203         leftDimen = CalcLength(
204             CalcDimension(leftOptional.value().Value(), static_cast<DimensionUnit>(leftOptional.value().Unit())));
205     }
206     NG::PaddingPropertyF oldPaddings;
207     NG::PaddingProperty paddings;
208     paddings.top = std::optional<CalcLength>(topDimen);
209     paddings.bottom = std::optional<CalcLength>(bottomDimen);
210     paddings.left = std::optional<CalcLength>(leftDimen);
211     paddings.right = std::optional<CalcLength>(rightDimen);
212     ToggleModelNG::SetPadding(frameNode, oldPaddings, paddings);
213 }
214 
ResetTogglePadding(ArkUINodeHandle node)215 void ResetTogglePadding(ArkUINodeHandle node)
216 {
217     auto* frameNode = reinterpret_cast<FrameNode*>(node);
218     CHECK_NULL_VOID(frameNode);
219     NG::PaddingPropertyF oldPaddings;
220     NG::PaddingProperty paddings;
221     paddings.top = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
222     paddings.bottom = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
223     paddings.left = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
224     paddings.right = std::optional<CalcLength>(CalcLength(0.0, DimensionUnit::VP));
225     ToggleModelNG::SetPadding(frameNode, oldPaddings, paddings);
226 }
227 
SetToggleBackgroundColor(ArkUINodeHandle node,ArkUI_Uint32 color)228 void SetToggleBackgroundColor(ArkUINodeHandle node, ArkUI_Uint32 color)
229 {
230     auto* frameNode = reinterpret_cast<FrameNode*>(node);
231     CHECK_NULL_VOID(frameNode);
232     ToggleModelNG::SetBackgroundColor(frameNode, Color(color));
233 }
234 
ResetToggleBackgroundColor(ArkUINodeHandle node)235 void ResetToggleBackgroundColor(ArkUINodeHandle node)
236 {
237     auto* frameNode = reinterpret_cast<FrameNode*>(node);
238     CHECK_NULL_VOID(frameNode);
239     ToggleModelNG::SetBackgroundColor(frameNode, Color(Color::TRANSPARENT));
240 }
241 
SetToggleHoverEffect(ArkUINodeHandle node,ArkUI_Int32 hoverEffectValue)242 void SetToggleHoverEffect(ArkUINodeHandle node, ArkUI_Int32 hoverEffectValue)
243 {
244     auto* frameNode = reinterpret_cast<FrameNode*>(node);
245     CHECK_NULL_VOID(frameNode);
246     OHOS::Ace::HoverEffectType hoverEffect = OHOS::Ace::HoverEffectType::AUTO;
247     hoverEffect = static_cast<OHOS::Ace::HoverEffectType>(hoverEffectValue);
248     ToggleModelNG::SetHoverEffect(frameNode, hoverEffect);
249 }
250 
ResetToggleHoverEffect(ArkUINodeHandle node)251 void ResetToggleHoverEffect(ArkUINodeHandle node)
252 {
253     auto* frameNode = reinterpret_cast<FrameNode*>(node);
254     CHECK_NULL_VOID(frameNode);
255     ToggleModelNG::SetHoverEffect(frameNode, OHOS::Ace::HoverEffectType::AUTO);
256 }
257 
SetTogglePointRadius(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)258 void SetTogglePointRadius(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
259 {
260     auto* frameNode = reinterpret_cast<FrameNode*>(node);
261     CHECK_NULL_VOID(frameNode);
262     DimensionUnit unitValue = static_cast<DimensionUnit>(unit);
263     CalcDimension switchPointRadius = CalcDimension(value, unitValue);
264     ToggleModelNG::SetPointRadius(frameNode, switchPointRadius);
265 }
266 
ResetTogglePointRadius(ArkUINodeHandle node)267 void ResetTogglePointRadius(ArkUINodeHandle node)
268 {
269     auto* frameNode = reinterpret_cast<FrameNode*>(node);
270     CHECK_NULL_VOID(frameNode);
271     ToggleModelNG::ResetPointRadius(frameNode);
272 }
273 
SetToggleUnselectedColor(ArkUINodeHandle node,ArkUI_Uint32 unselectedColor)274 void SetToggleUnselectedColor(ArkUINodeHandle node, ArkUI_Uint32 unselectedColor)
275 {
276     auto* frameNode = reinterpret_cast<FrameNode*>(node);
277     CHECK_NULL_VOID(frameNode);
278     ToggleModelNG::SetUnselectedColor(frameNode, Color(unselectedColor));
279 }
280 
ResetToggleUnselectedColor(ArkUINodeHandle node)281 void ResetToggleUnselectedColor(ArkUINodeHandle node)
282 {
283     auto* frameNode = reinterpret_cast<FrameNode*>(node);
284     CHECK_NULL_VOID(frameNode);
285     auto context = frameNode->GetContext();
286     CHECK_NULL_VOID(context);
287     auto themeManager = context->GetThemeManager();
288     CHECK_NULL_VOID(themeManager);
289     auto switchTheme = themeManager->GetTheme<SwitchTheme>();
290     CHECK_NULL_VOID(switchTheme);
291     Color unselectedColor;
292     if (switchTheme) {
293         unselectedColor = switchTheme->GetInactiveColor();
294     }
295     ToggleModelNG::SetUnselectedColor(frameNode, unselectedColor);
296 }
297 
SetToggleTrackBorderRadius(ArkUINodeHandle node,ArkUI_Float32 value,ArkUI_Int32 unit)298 void SetToggleTrackBorderRadius(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit)
299 {
300     auto* frameNode = reinterpret_cast<FrameNode*>(node);
301     CHECK_NULL_VOID(frameNode);
302     DimensionUnit unitValue = static_cast<DimensionUnit>(unit);
303     CalcDimension borderRadius = CalcDimension(value, unitValue);
304     ToggleModelNG::SetTrackBorderRadius(frameNode, borderRadius);
305 }
306 
ResetToggleTrackBorderRadius(ArkUINodeHandle node)307 void ResetToggleTrackBorderRadius(ArkUINodeHandle node)
308 {
309     auto* frameNode = reinterpret_cast<FrameNode*>(node);
310     CHECK_NULL_VOID(frameNode);
311     ToggleModelNG::ResetTrackBorderRadius(frameNode);
312 }
313 
SetToggleIsOn(ArkUINodeHandle node,ArkUI_Bool switchPointColor)314 void SetToggleIsOn(ArkUINodeHandle node, ArkUI_Bool switchPointColor)
315 {
316     auto* frameNode = reinterpret_cast<FrameNode*>(node);
317     CHECK_NULL_VOID(frameNode);
318     ToggleModelNG::SetSwitchIsOn(frameNode, static_cast<bool>(switchPointColor));
319 }
320 
ResetToggleIsOn(ArkUINodeHandle node)321 void ResetToggleIsOn(ArkUINodeHandle node)
322 {
323     auto* frameNode = reinterpret_cast<FrameNode*>(node);
324     CHECK_NULL_VOID(frameNode);
325     ToggleModelNG::SetSwitchIsOn(frameNode, false);
326 }
327 
GetToggleIsOn(ArkUINodeHandle node)328 ArkUI_Bool GetToggleIsOn(ArkUINodeHandle node)
329 {
330     auto* frameNode = reinterpret_cast<FrameNode*>(node);
331     CHECK_NULL_RETURN(frameNode, ERROR_UINT_CODE);
332     return static_cast<ArkUI_Bool>(ToggleModelNG::GetSwitchIsOn(frameNode));
333 }
334 
GetToggleUnselectedColor(ArkUINodeHandle node)335 ArkUI_Uint32 GetToggleUnselectedColor(ArkUINodeHandle node)
336 {
337     auto* frameNode = reinterpret_cast<FrameNode*>(node);
338     CHECK_NULL_RETURN(frameNode, ERROR_UINT_CODE);
339     return ToggleModelNG::GetUnselectedColor(frameNode).GetValue();
340 }
341 } // namespace
342 namespace NodeModifier {
GetToggleModifier()343 const ArkUIToggleModifier* GetToggleModifier()
344 {
345     static const ArkUIToggleModifier modifier = {
346         SetToggleSelectedColor,
347         ResetToggleSelectedColor,
348         SetToggleSwitchPointColor,
349         ResetToggleSwitchPointColor,
350         SetToggleHeight,
351         ResetToggleHeight,
352         SetToggleResponseRegion,
353         ResetToggleResponseRegion,
354         SetTogglePadding,
355         ResetTogglePadding,
356         SetToggleBackgroundColor,
357         ResetToggleBackgroundColor,
358         SetToggleHoverEffect,
359         ResetToggleHoverEffect,
360         GetToggleSelectedColor,
361         GetToggleSwitchPointColor,
362         SetToggleIsOn,
363         ResetToggleIsOn,
364         GetToggleIsOn,
365         SetTogglePointRadius,
366         ResetTogglePointRadius,
367         SetToggleUnselectedColor,
368         ResetToggleUnselectedColor,
369         SetToggleTrackBorderRadius,
370         ResetToggleTrackBorderRadius,
371         GetToggleUnselectedColor,
372     };
373 
374     return &modifier;
375 }
376 
GetCJUIToggleModifier()377 const CJUIToggleModifier* GetCJUIToggleModifier()
378 {
379     static const CJUIToggleModifier modifier = {
380         SetToggleSelectedColor,
381         ResetToggleSelectedColor,
382         SetToggleSwitchPointColor,
383         ResetToggleSwitchPointColor,
384         SetToggleHeight,
385         ResetToggleHeight,
386         SetToggleResponseRegion,
387         ResetToggleResponseRegion,
388         SetTogglePadding,
389         ResetTogglePadding,
390         SetToggleBackgroundColor,
391         ResetToggleBackgroundColor,
392         SetToggleHoverEffect,
393         ResetToggleHoverEffect,
394         GetToggleSelectedColor,
395         GetToggleSwitchPointColor,
396         SetToggleIsOn,
397         ResetToggleIsOn,
398         GetToggleIsOn,
399         SetTogglePointRadius,
400         ResetTogglePointRadius,
401         SetToggleUnselectedColor,
402         ResetToggleUnselectedColor,
403         SetToggleTrackBorderRadius,
404         ResetToggleTrackBorderRadius,
405         GetToggleUnselectedColor,
406     };
407 
408     return &modifier;
409 }
410 
SetOnToggleChange(ArkUINodeHandle node,void * extraParam)411 void SetOnToggleChange(ArkUINodeHandle node, void* extraParam)
412 {
413     auto* frameNode = reinterpret_cast<FrameNode*>(node);
414     CHECK_NULL_VOID(frameNode);
415     auto onChange = [node, extraParam](const bool isOn) {
416         ArkUINodeEvent event;
417         event.kind = COMPONENT_ASYNC_EVENT;
418         event.extraParam = reinterpret_cast<intptr_t>(extraParam);
419         event.componentAsyncEvent.subKind = ON_TOGGLE_CHANGE;
420         event.componentAsyncEvent.data[0].u32 = isOn;
421         SendArkUIAsyncEvent(&event);
422     };
423     ToggleModelNG::OnChange(frameNode, std::move(onChange));
424 }
425 
ResetOnToggleChange(ArkUINodeHandle node)426 void ResetOnToggleChange(ArkUINodeHandle node)
427 {
428     auto* frameNode = reinterpret_cast<FrameNode*>(node);
429     CHECK_NULL_VOID(frameNode);
430     ToggleModelNG::OnChange(frameNode, nullptr);
431 }
432 } // namespace NodeModifier
433 } // namespace OHOS::Ace::NG
434