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