1 /*
2 * Copyright (c) 2022 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 "core/components_ng/pattern/radio/radio_pattern.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components/checkable/checkable_theme.h"
20 #include "core/components/common/layout/constants.h"
21 #include "core/components_ng/base/view_stack_processor.h"
22 #include "core/components_ng/pattern/radio/radio_layout_algorithm.h"
23 #include "core/components_ng/pattern/radio/radio_paint_property.h"
24 #include "core/components_ng/pattern/stage/page_event_hub.h"
25 #include "core/components_ng/property/property.h"
26 #include "core/event/touch_event.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28
29 namespace OHOS::Ace::NG {
30
31 namespace {
32 constexpr int DEFAULT_RADIO_ANIMATION_DURATION = 300;
33 constexpr float DEFAULT_MID_TIME_SLOT = 0.5;
34 constexpr float DEFAULT_END_TIME_SLOT = 1.0;
35 constexpr float DEFAULT_SHRINK_TIME_SLOT = 0.9;
36 } // namespace
37
OnAttachToFrameNode()38 void RadioPattern::OnAttachToFrameNode()
39 {
40 auto host = GetHost();
41 CHECK_NULL_VOID(host);
42 host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
43 }
44
OnDetachFromFrameNode(FrameNode * frameNode)45 void RadioPattern::OnDetachFromFrameNode(FrameNode* frameNode)
46 {
47 CHECK_NULL_VOID(frameNode);
48 auto pipelineContext = PipelineContext::GetCurrentContext();
49 CHECK_NULL_VOID(pipelineContext);
50 auto stageManager = pipelineContext->GetStageManager();
51 CHECK_NULL_VOID(stageManager);
52 auto pageNode = stageManager->GetLastPage();
53 CHECK_NULL_VOID(pageNode);
54 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
55 CHECK_NULL_VOID(pageEventHub);
56 auto radioEventHub = frameNode->GetEventHub<NG::RadioEventHub>();
57 CHECK_NULL_VOID(radioEventHub);
58 pageEventHub->RemoveRadioFromGroup(radioEventHub->GetGroup(), frameNode->GetId());
59 }
60
OnModifyDone()61 void RadioPattern::OnModifyDone()
62 {
63 UpdateState();
64 auto host = GetHost();
65 CHECK_NULL_VOID(host);
66 auto pipeline = PipelineBase::GetCurrentContext();
67 CHECK_NULL_VOID(pipeline);
68 auto radioTheme = pipeline->GetTheme<RadioTheme>();
69 CHECK_NULL_VOID(radioTheme);
70 auto layoutProperty = host->GetLayoutProperty();
71 CHECK_NULL_VOID(layoutProperty);
72 if (!layoutProperty->GetMarginProperty()) {
73 MarginProperty margin;
74 margin.left = CalcLength(radioTheme->GetHotZoneHorizontalPadding().Value());
75 margin.right = CalcLength(radioTheme->GetHotZoneHorizontalPadding().Value());
76 margin.top = CalcLength(radioTheme->GetHotZoneVerticalPadding().Value());
77 margin.bottom = CalcLength(radioTheme->GetHotZoneVerticalPadding().Value());
78 layoutProperty->UpdateMargin(margin);
79 }
80 hotZoneHorizontalPadding_ = radioTheme->GetHotZoneHorizontalPadding();
81 hotZoneVerticalPadding_ = radioTheme->GetHotZoneVerticalPadding();
82 InitClickEvent();
83 InitTouchEvent();
84 InitMouseEvent();
85 auto focusHub = host->GetFocusHub();
86 CHECK_NULL_VOID(focusHub);
87 InitOnKeyEvent(focusHub);
88 }
89
InitClickEvent()90 void RadioPattern::InitClickEvent()
91 {
92 if (clickListener_) {
93 return;
94 }
95 auto host = GetHost();
96 CHECK_NULL_VOID(host);
97 auto gesture = host->GetOrCreateGestureEventHub();
98 CHECK_NULL_VOID(gesture);
99 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
100 auto radioPattern = weak.Upgrade();
101 CHECK_NULL_VOID(radioPattern);
102 radioPattern->OnClick();
103 };
104 clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
105 gesture->AddClickEvent(clickListener_);
106 }
107
InitTouchEvent()108 void RadioPattern::InitTouchEvent()
109 {
110 if (touchListener_) {
111 return;
112 }
113 auto host = GetHost();
114 CHECK_NULL_VOID(host);
115 auto gesture = host->GetOrCreateGestureEventHub();
116 CHECK_NULL_VOID(gesture);
117 auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
118 auto radioPattern = weak.Upgrade();
119 CHECK_NULL_VOID(radioPattern);
120 if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
121 radioPattern->OnTouchDown();
122 }
123 if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
124 info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
125 radioPattern->OnTouchUp();
126 }
127 };
128 touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
129 gesture->AddTouchEvent(touchListener_);
130 }
131
InitMouseEvent()132 void RadioPattern::InitMouseEvent()
133 {
134 if (mouseEvent_) {
135 return;
136 }
137 auto host = GetHost();
138 CHECK_NULL_VOID(host);
139 auto gesture = host->GetOrCreateGestureEventHub();
140 CHECK_NULL_VOID(gesture);
141 auto eventHub = host->GetEventHub<RadioEventHub>();
142 auto inputHub = eventHub->GetOrCreateInputEventHub();
143
144 auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
145 auto pattern = weak.Upgrade();
146 if (pattern) {
147 pattern->HandleMouseEvent(isHover);
148 }
149 };
150 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
151 inputHub->AddOnHoverEvent(mouseEvent_);
152 }
153
HandleMouseEvent(bool isHover)154 void RadioPattern::HandleMouseEvent(bool isHover)
155 {
156 isHover_ = isHover;
157 if (isHover) {
158 touchHoverType_ = TouchHoverAnimationType::HOVER;
159 } else {
160 touchHoverType_ = TouchHoverAnimationType::NONE;
161 }
162 auto host = GetHost();
163 CHECK_NULL_VOID(host);
164 host->MarkNeedRenderOnly();
165 }
166
OnClick()167 void RadioPattern::OnClick()
168 {
169 auto host = GetHost();
170 CHECK_NULL_VOID(host);
171 auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
172 CHECK_NULL_VOID(paintProperty);
173 bool check = false;
174 if (paintProperty->HasRadioCheck()) {
175 check = paintProperty->GetRadioCheckValue();
176 } else {
177 paintProperty->UpdateRadioCheck(false);
178 }
179
180 if (!preCheck_ && !check) {
181 paintProperty->UpdateRadioCheck(true);
182 UpdateState();
183 }
184 }
185
OnTouchDown()186 void RadioPattern::OnTouchDown()
187 {
188 if (isHover_) {
189 touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
190 } else {
191 touchHoverType_ = TouchHoverAnimationType::PRESS;
192 }
193 auto host = GetHost();
194 CHECK_NULL_VOID(host);
195 host->MarkNeedRenderOnly();
196 }
197
OnTouchUp()198 void RadioPattern::OnTouchUp()
199 {
200 if (isHover_) {
201 touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
202 } else {
203 touchHoverType_ = TouchHoverAnimationType::NONE;
204 }
205 auto host = GetHost();
206 CHECK_NULL_VOID(host);
207 host->MarkNeedRenderOnly();
208 }
209
UpdateState()210 void RadioPattern::UpdateState()
211 {
212 auto host = GetHost();
213 CHECK_NULL_VOID(host);
214 auto pattern = host->GetPattern<RadioPattern>();
215 CHECK_NULL_VOID(pattern);
216 auto eventHub = host->GetEventHub<RadioEventHub>();
217 CHECK_NULL_VOID(eventHub);
218
219 auto preGroup = pattern->GetPreGroup();
220 auto group = eventHub->GetGroup();
221 if (!preGroup.has_value()) {
222 auto pipelineContext = PipelineContext::GetCurrentContext();
223 CHECK_NULL_VOID(pipelineContext);
224 auto stageManager = pipelineContext->GetStageManager();
225 CHECK_NULL_VOID(stageManager);
226 auto pageNode = stageManager->GetLastPage();
227 CHECK_NULL_VOID(pageNode);
228 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
229 CHECK_NULL_VOID(pageEventHub);
230 pageEventHub->AddRadioToGroup(group, host->GetId());
231 } else {
232 if (preGroup.value() != group) {
233 auto pipelineContext = PipelineContext::GetCurrentContext();
234 CHECK_NULL_VOID(pipelineContext);
235 auto stageManager = pipelineContext->GetStageManager();
236 CHECK_NULL_VOID(stageManager);
237 auto pageNode = stageManager->GetLastPage();
238 CHECK_NULL_VOID(pageNode);
239 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
240 CHECK_NULL_VOID(pageEventHub);
241
242 pageEventHub->RemoveRadioFromGroup(preGroup.value(), host->GetId());
243 pageEventHub->AddRadioToGroup(group, host->GetId());
244 }
245 }
246 pattern->SetPreGroup(group);
247
248 auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
249 CHECK_NULL_VOID(paintProperty);
250
251 bool check = false;
252 if (paintProperty->HasRadioCheck()) {
253 check = paintProperty->GetRadioCheckValue();
254 /*
255 * Do not set isFirstCreated_ to false if the radio is set to true at creation time. The isFirstCreated_ is set
256 * to false in UpdateGroupCheckStatus because isFirstCreated_ is also required to determine if an onChange event
257 * needs to be triggered.
258 */
259 if (check) {
260 UpdateUIStatus(true);
261 if (!isFirstCreated_) {
262 PlayAnimation(true);
263 }
264 } else {
265 // If the radio is set to false, set isFirstCreated_ to false.
266 isFirstCreated_ = false;
267 }
268 } else {
269 paintProperty->UpdateRadioCheck(false);
270 // If the radio check is not set, set isFirstCreated_ to false.
271 isFirstCreated_ = false;
272 }
273 if (preCheck_ != check) {
274 UpdateGroupCheckStatus(host, check);
275 }
276 preCheck_ = check;
277 }
278
UpdateUncheckStatus(const RefPtr<FrameNode> & frameNode)279 void RadioPattern::UpdateUncheckStatus(const RefPtr<FrameNode>& frameNode)
280 {
281 auto radioPaintProperty = frameNode->GetPaintProperty<RadioPaintProperty>();
282 CHECK_NULL_VOID(radioPaintProperty);
283 radioPaintProperty->UpdateRadioCheck(false);
284 frameNode->MarkNeedRenderOnly();
285
286 if (preCheck_) {
287 auto radioEventHub = GetEventHub<RadioEventHub>();
288 CHECK_NULL_VOID(radioEventHub);
289 radioEventHub->UpdateChangeEvent(false);
290 PlayAnimation(false);
291 }
292 preCheck_ = false;
293 }
294
UpdateGroupCheckStatus(const RefPtr<FrameNode> & frameNode,bool check)295 void RadioPattern::UpdateGroupCheckStatus(const RefPtr<FrameNode>& frameNode, bool check)
296 {
297 frameNode->MarkNeedRenderOnly();
298
299 auto pipelineContext = PipelineContext::GetCurrentContext();
300 CHECK_NULL_VOID(pipelineContext);
301 auto stageManager = pipelineContext->GetStageManager();
302 CHECK_NULL_VOID(stageManager);
303 auto pageNode = stageManager->GetLastPage();
304 CHECK_NULL_VOID(pageNode);
305 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
306 CHECK_NULL_VOID(pageEventHub);
307
308 auto radioEventHub = GetEventHub<RadioEventHub>();
309 CHECK_NULL_VOID(radioEventHub);
310 if (check) {
311 pageEventHub->UpdateRadioGroupValue(radioEventHub->GetGroup(), frameNode->GetId());
312 } else {
313 auto radioPaintProperty = frameNode->GetPaintProperty<RadioPaintProperty>();
314 CHECK_NULL_VOID(radioPaintProperty);
315 radioPaintProperty->UpdateRadioCheck(check);
316 PlayAnimation(false);
317 }
318
319 if (!isFirstCreated_) {
320 radioEventHub->UpdateChangeEvent(check);
321 }
322 // If the radio is set to true at creation time, set isFirstCreated_ to false here.
323 isFirstCreated_ = false;
324 }
325
PlayAnimation(bool isOn)326 void RadioPattern::PlayAnimation(bool isOn)
327 {
328 auto host = GetHost();
329 CHECK_NULL_VOID(host);
330 if (!onController_) {
331 onController_ = AceType::MakeRefPtr<Animator>(host->GetContext());
332 onController_->AddStopListener(Animator::StatusCallback([weak = AceType::WeakClaim(this)]() {
333 auto radio = weak.Upgrade();
334 if (radio) {
335 radio->UpdateUIStatus(true);
336 }
337 }));
338 }
339 if (!offController_) {
340 offController_ = AceType::MakeRefPtr<Animator>(host->GetContext());
341 offController_->AddStopListener(Animator::StatusCallback([weak = AceType::WeakClaim(this)]() {
342 auto radio = weak.Upgrade();
343 if (radio) {
344 radio->UpdateUIStatus(false);
345 }
346 }));
347 }
348 StopTranslateAnimation();
349 RefPtr<KeyframeAnimation<float>> shrinkEngine = AceType::MakeRefPtr<KeyframeAnimation<float>>();
350 RefPtr<KeyframeAnimation<float>> selectEngine = AceType::MakeRefPtr<KeyframeAnimation<float>>();
351 RefPtr<KeyframeAnimation<float>> selectRingEngine = AceType::MakeRefPtr<KeyframeAnimation<float>>();
352 onController_->ClearInterpolators();
353 offController_->ClearInterpolators();
354 auto shrinkFrameStart = AceType::MakeRefPtr<Keyframe<float>>(0.0, 1.0);
355 auto shrinkFrameMid = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_MID_TIME_SLOT, DEFAULT_SHRINK_TIME_SLOT);
356 auto shrinkFrameEnd = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_END_TIME_SLOT, 1.0);
357 shrinkEngine->AddKeyframe(shrinkFrameStart);
358 shrinkEngine->AddKeyframe(shrinkFrameMid);
359 shrinkEngine->AddKeyframe(shrinkFrameEnd);
360 shrinkEngine->SetCurve(Curves::FRICTION);
361 shrinkEngine->AddListener(Animation<float>::ValueCallback([weak = AceType::WeakClaim(this)](float value) {
362 auto radio = weak.Upgrade();
363 if (radio) {
364 radio->UpdateTotalScale(value);
365 }
366 }));
367
368 auto selectFrameStart = AceType::MakeRefPtr<Keyframe<float>>(0.0, isOn ? 0.0 : 0.5);
369 auto selectFrameMid = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_MID_TIME_SLOT, 0.0);
370 auto selectFrameEnd = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_END_TIME_SLOT, isOn ? 0.5 : 0.0);
371 selectEngine->AddKeyframe(selectFrameStart);
372 selectEngine->AddKeyframe(selectFrameMid);
373 selectEngine->AddKeyframe(selectFrameEnd);
374 selectEngine->SetCurve(Curves::FRICTION);
375 selectEngine->AddListener(Animation<float>::ValueCallback([weak = AceType::WeakClaim(this)](float value) {
376 auto radio = weak.Upgrade();
377 if (radio) {
378 radio->UpdatePointScale(value);
379 }
380 }));
381
382 auto selectRingFrameStart = AceType::MakeRefPtr<Keyframe<float>>(0.0, isOn ? 1.0 : 0.0);
383 auto selectRingFrameMid = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_MID_TIME_SLOT, 0.0);
384 auto selectRingFrameEnd = AceType::MakeRefPtr<Keyframe<float>>(DEFAULT_END_TIME_SLOT, isOn ? 0.0 : 1.0);
385 selectRingEngine->AddKeyframe(selectRingFrameStart);
386 selectRingEngine->AddKeyframe(selectRingFrameMid);
387 selectRingEngine->AddKeyframe(selectRingFrameEnd);
388 selectRingEngine->SetCurve(Curves::FRICTION);
389 selectRingEngine->AddListener(Animation<float>::ValueCallback([weak = AceType::WeakClaim(this)](float value) {
390 auto radio = weak.Upgrade();
391 if (radio) {
392 radio->UpdateRingPointScale(value);
393 }
394 }));
395
396 if (isOn) {
397 onController_->AddInterpolator(shrinkEngine);
398 onController_->AddInterpolator(selectEngine);
399 onController_->AddInterpolator(selectRingEngine);
400 onController_->SetDuration(DEFAULT_RADIO_ANIMATION_DURATION);
401 onController_->Play();
402 } else {
403 offController_->AddInterpolator(shrinkEngine);
404 offController_->AddInterpolator(selectEngine);
405 offController_->AddInterpolator(selectRingEngine);
406 offController_->SetDuration(DEFAULT_RADIO_ANIMATION_DURATION);
407 offController_->Play();
408 }
409 }
410
StopTranslateAnimation()411 void RadioPattern::StopTranslateAnimation()
412 {
413 if (offController_ && !offController_->IsStopped()) {
414 offController_->Stop();
415 }
416 if (onController_ && !onController_->IsStopped()) {
417 onController_->Stop();
418 }
419 }
420
UpdateUIStatus(bool check)421 void RadioPattern::UpdateUIStatus(bool check)
422 {
423 uiStatus_ = check ? UIStatus::SELECTED : UIStatus::UNSELECTED;
424 auto host = GetHost();
425 CHECK_NULL_VOID(host);
426 host->MarkNeedRenderOnly();
427 }
428
UpdateTotalScale(float scale)429 void RadioPattern::UpdateTotalScale(float scale)
430 {
431 totalScale_ = scale;
432 auto host = GetHost();
433 CHECK_NULL_VOID(host);
434 host->MarkNeedRenderOnly();
435 }
436
UpdatePointScale(float scale)437 void RadioPattern::UpdatePointScale(float scale)
438 {
439 pointScale_ = scale;
440 auto host = GetHost();
441 CHECK_NULL_VOID(host);
442 host->MarkNeedRenderOnly();
443 }
444
UpdateRingPointScale(float scale)445 void RadioPattern::UpdateRingPointScale(float scale)
446 {
447 ringPointScale_ = scale;
448 auto host = GetHost();
449 CHECK_NULL_VOID(host);
450 host->MarkNeedRenderOnly();
451 }
452
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)453 void RadioPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
454 {
455 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
456 auto pattern = wp.Upgrade();
457 if (!pattern) {
458 return false;
459 }
460 return pattern->OnKeyEvent(event);
461 };
462 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
463
464 auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
465 auto pattern = wp.Upgrade();
466 if (pattern) {
467 pattern->GetInnerFocusPaintRect(paintRect);
468 }
469 };
470 focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
471 }
472
OnKeyEvent(const KeyEvent & event)473 bool RadioPattern::OnKeyEvent(const KeyEvent& event)
474 {
475 if (event.action != KeyAction::DOWN) {
476 return false;
477 }
478 if (event.code == KeyCode::KEY_ENTER) {
479 OnClick();
480 return true;
481 }
482 return false;
483 }
484
GetInnerFocusPaintRect(RoundRect & paintRect)485 void RadioPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
486 {
487 auto pipeline = PipelineBase::GetCurrentContext();
488 CHECK_NULL_VOID(pipeline);
489 auto radioTheme = pipeline->GetTheme<RadioTheme>();
490 CHECK_NULL_VOID(radioTheme);
491 auto focusPaintPadding = radioTheme->GetFocusPaintPadding().ConvertToPx();
492 float outCircleRadius = size_.Width() / 2 + focusPaintPadding;
493 float originX = offset_.GetX() - focusPaintPadding;
494 float originY = offset_.GetY() - focusPaintPadding;
495 float width = size_.Width() + 2 * focusPaintPadding;
496 float height = size_.Height() + 2 * focusPaintPadding;
497 paintRect.SetRect({ originX, originY, width, height });
498 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, outCircleRadius, outCircleRadius);
499 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, outCircleRadius, outCircleRadius);
500 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, outCircleRadius, outCircleRadius);
501 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, outCircleRadius, outCircleRadius);
502 }
503
GetFocusPattern() const504 FocusPattern RadioPattern::GetFocusPattern() const
505 {
506 auto pipeline = PipelineBase::GetCurrentContext();
507 CHECK_NULL_RETURN(pipeline, FocusPattern());
508 auto radioTheme = pipeline->GetTheme<RadioTheme>();
509 CHECK_NULL_RETURN(radioTheme, FocusPattern());
510 auto activeColor = radioTheme->GetActiveColor();
511 FocusPaintParam focusPaintParam;
512 focusPaintParam.SetPaintColor(activeColor);
513 return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
514 }
515
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig &)516 bool RadioPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& /*config*/)
517 {
518 auto geometryNode = dirty->GetGeometryNode();
519 offset_ = geometryNode->GetContentOffset();
520 size_ = geometryNode->GetContentSize();
521
522 auto offset = geometryNode->GetContentOffset();
523 auto size = geometryNode->GetContentSize();
524 if (offset != offset_ || size != size_) {
525 offset_ = offset;
526 size_ = size;
527 AddHotZoneRect();
528 }
529
530 return true;
531 }
532
533 // Set the default hot zone for the component.
AddHotZoneRect()534 void RadioPattern::AddHotZoneRect()
535 {
536 hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
537 hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
538 hotZoneSize_.SetWidth(size_.Width() + 2 * hotZoneHorizontalPadding_.ConvertToPx());
539 hotZoneSize_.SetHeight(size_.Height() + 2 * hotZoneVerticalPadding_.ConvertToPx());
540 DimensionRect hotZoneRegion;
541 hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
542 hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
543 auto host = GetHost();
544 CHECK_NULL_VOID(host);
545 host->AddHotZoneRect(hotZoneRegion);
546 }
547
RemoveLastHotZoneRect() const548 void RadioPattern::RemoveLastHotZoneRect() const
549 {
550 auto host = GetHost();
551 CHECK_NULL_VOID(host);
552 host->RemoveLastHotZoneRect();
553 }
554
555 } // namespace OHOS::Ace::NG
556