• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 
16 #include "core/components_ng/pattern/radio/radio_pattern.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/utils/multi_thread.h"
20 #include "core/components/theme/icon_theme.h"
21 #include "core/components_ng/pattern/image/image_pattern.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 
24 namespace OHOS::Ace::NG {
25 
26 namespace {
27 constexpr int FOR_HOTZONESIZE_CALCULATE_MULTIPLY_TWO = 2;
28 const Color ITEM_FILL_COLOR = Color::TRANSPARENT;
29 
30 constexpr int32_t DEFAULT_RADIO_ANIMATION_DURATION = 200;
31 constexpr int32_t DEFAULT_RADIO_ANIMATION_DURATION_CIRCLE = 150;
32 constexpr float INDICATOR_MIN_SCALE = 0.8F;
33 constexpr float INDICATOR_MAX_SCALE = 1.0F;
34 constexpr float INDICATOR_MIN_OPACITY = 0.0F;
35 constexpr float INDICATOR_MAX_OPACITY = 1.0F;
36 constexpr int32_t RADIO_PADDING_COUNT = 2;
37 
38 constexpr float DEFAULT_INTERPOLATINGSPRING_VELOCITY = 0.0f;
39 constexpr float DEFAULT_INTERPOLATINGSPRING_MASS = 1.0f;
40 constexpr float DEFAULT_INTERPOLATINGSPRING_STIFFNESS = 728.0f;
41 constexpr float DEFAULT_INTERPOLATINGSPRING_DAMPING = 46.0f;
42 constexpr Color DEFAULT_INDICATOR_DARK_LIGHT_COLOR = Color(0xffffffff);
43 } // namespace
44 
OnAttachToFrameNode()45 void RadioPattern::OnAttachToFrameNode()
46 {
47     auto host = GetHost();
48     CHECK_NULL_VOID(host);
49     host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
50 }
51 
UpdateGroupStatus(FrameNode * frameNode)52 void RadioPattern::UpdateGroupStatus(FrameNode* frameNode)
53 {
54     CHECK_NULL_VOID(frameNode);
55     auto groupManager = GetGroupManager();
56     CHECK_NULL_VOID(groupManager);
57     auto radioEventHub = frameNode->GetOrCreateEventHub<NG::RadioEventHub>();
58     CHECK_NULL_VOID(radioEventHub);
59     groupManager->RemoveRadioFromGroup(radioEventHub->GetGroup(), frameNode->GetId());
60 }
61 
OnDetachFromFrameNode(FrameNode * frameNode)62 void RadioPattern::OnDetachFromFrameNode(FrameNode* frameNode)
63 {
64     THREAD_SAFE_NODE_CHECK(frameNode, OnDetachFromFrameNode);
65     UpdateGroupStatus(frameNode);
66 }
67 
OnDetachFromMainTree()68 void RadioPattern::OnDetachFromMainTree()
69 {
70     auto host = GetHost();
71     THREAD_SAFE_NODE_CHECK(host, OnDetachFromMainTree, host);
72 }
73 
SetBuilderState()74 void RadioPattern::SetBuilderState()
75 {
76     CHECK_NULL_VOID(builderChildNode_);
77     auto renderContext = builderChildNode_->GetRenderContext();
78     CHECK_NULL_VOID(renderContext);
79     renderContext->UpdateOpacity(0);
80     auto layoutProperty = builderChildNode_->GetLayoutProperty();
81     CHECK_NULL_VOID(layoutProperty);
82     layoutProperty->UpdateVisibility(VisibleType::GONE);
83 }
84 
UpdateIndicatorType()85 void RadioPattern::UpdateIndicatorType()
86 {
87     auto host = GetHost();
88     CHECK_NULL_VOID(host);
89     auto radioPaintProperty = host->GetPaintProperty<RadioPaintProperty>();
90     CHECK_NULL_VOID(radioPaintProperty);
91     auto radioIndicatorType = radioPaintProperty->GetRadioIndicator().value_or(0);
92     if (radioIndicatorType == static_cast<int32_t>(RadioIndicatorType::CUSTOM)) {
93         LoadBuilder();
94     } else {
95         ImageNodeCreate();
96     }
97     CHECK_NULL_VOID(builderChildNode_);
98     auto renderContext = builderChildNode_->GetRenderContext();
99     CHECK_NULL_VOID(renderContext);
100     renderContext->UpdateTransformScale({ INDICATOR_MAX_SCALE, INDICATOR_MAX_SCALE });
101     renderContext->UpdateOpacity(1);
102     if (!radioPaintProperty->GetRadioCheckValue(false)) {
103         SetBuilderState();
104     }
105 }
106 
OnModifyDone()107 void RadioPattern::OnModifyDone()
108 {
109     Pattern::OnModifyDone();
110     FireBuilder();
111     auto host = GetHost();
112     CHECK_NULL_VOID(host);
113     auto* pipeline = host->GetContext();
114     CHECK_NULL_VOID(pipeline);
115     auto radioTheme = pipeline->GetTheme<RadioTheme>();
116     CHECK_NULL_VOID(radioTheme);
117     if (!makeFunc_.has_value() && host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
118         auto radioPaintProperty = host->GetPaintProperty<RadioPaintProperty>();
119         if (!radioModifier_) {
120             radioModifier_ = AceType::MakeRefPtr<RadioModifier>();
121         }
122         if (radioPaintProperty && !radioPaintProperty->HasRadioCheck()) {
123             radioPaintProperty->UpdateRadioCheck(false);
124         }
125         if (radioPaintProperty && !radioPaintProperty->GetRadioCheckValue()) {
126             radioModifier_->InitOpacityScale(false);
127         }
128         auto callback = [weak = WeakClaim(this)]() {
129             auto radio = weak.Upgrade();
130             if (radio) {
131                 radio->UpdateIndicatorType();
132             }
133         };
134         pipeline->AddBuildFinishCallBack(callback);
135     }
136     UpdateState();
137     hotZoneHorizontalPadding_ = radioTheme->GetHotZoneHorizontalPadding();
138     hotZoneVerticalPadding_ = radioTheme->GetHotZoneVerticalPadding();
139     InitDefaultMargin();
140     HandleEnabled();
141     InitClickEvent();
142     InitTouchEvent();
143     InitMouseEvent();
144     InitFocusEvent();
145     auto focusHub = host->GetFocusHub();
146     CHECK_NULL_VOID(focusHub);
147     InitOnKeyEvent(focusHub);
148     SetAccessibilityAction();
149 }
150 
InitDefaultMargin()151 void RadioPattern::InitDefaultMargin()
152 {
153     if (makeFunc_.has_value()) {
154         ResetDefaultMargin();
155         return;
156     }
157     auto host = GetHost();
158     CHECK_NULL_VOID(host);
159     auto layoutProperty = host->GetLayoutProperty();
160     CHECK_NULL_VOID(layoutProperty);
161     MarginProperty margin;
162     margin.left = CalcLength(hotZoneHorizontalPadding_.Value());
163     margin.right = CalcLength(hotZoneHorizontalPadding_.Value());
164     margin.top = CalcLength(hotZoneVerticalPadding_.Value());
165     margin.bottom = CalcLength(hotZoneVerticalPadding_.Value());
166     auto& setMargin = layoutProperty->GetMarginProperty();
167     if (setMargin) {
168         if (setMargin->left.has_value()) {
169             margin.left = setMargin->left;
170         }
171         if (setMargin->right.has_value()) {
172             margin.right = setMargin->right;
173         }
174         if (setMargin->top.has_value()) {
175             margin.top = setMargin->top;
176         }
177         if (setMargin->bottom.has_value()) {
178             margin.bottom = setMargin->bottom;
179         }
180     }
181     layoutProperty->UpdateMargin(margin);
182 }
183 
ResetDefaultMargin()184 void RadioPattern::ResetDefaultMargin()
185 {
186     if (isUserSetMargin_) {
187         return;
188     }
189     auto host = GetHost();
190     CHECK_NULL_VOID(host);
191     auto layoutProperty = host->GetLayoutProperty();
192     CHECK_NULL_VOID(layoutProperty);
193     MarginProperty margin;
194     layoutProperty->UpdateMargin(margin);
195 }
196 
InitFocusEvent()197 void RadioPattern::InitFocusEvent()
198 {
199     if (focusEventInitialized_) {
200         return;
201     }
202     auto host = GetHost();
203     CHECK_NULL_VOID(host);
204     auto focusHub = host->GetOrCreateFocusHub();
205     CHECK_NULL_VOID(focusHub);
206     auto focusTask = [weak = WeakClaim(this)](FocusReason reason) {
207         auto pattern = weak.Upgrade();
208         CHECK_NULL_VOID(pattern);
209         pattern->HandleFocusEvent();
210     };
211     focusHub->SetOnFocusInternal(focusTask);
212     auto blurTask = [weak = WeakClaim(this)]() {
213         auto pattern = weak.Upgrade();
214         CHECK_NULL_VOID(pattern);
215         pattern->HandleBlurEvent();
216     };
217     focusHub->SetOnBlurInternal(blurTask);
218     focusEventInitialized_ = true;
219 }
220 
HandleFocusEvent()221 void RadioPattern::HandleFocusEvent()
222 {
223     CHECK_NULL_VOID(radioModifier_);
224     AddIsFocusActiveUpdateEvent();
225     auto pipeline = PipelineContext::GetCurrentContext();
226     CHECK_NULL_VOID(pipeline);
227     if (pipeline->GetIsFocusActive()) {
228         OnIsFocusActiveUpdate(true);
229     }
230 }
231 
HandleBlurEvent()232 void RadioPattern::HandleBlurEvent()
233 {
234     CHECK_NULL_VOID(radioModifier_);
235     RemoveIsFocusActiveUpdateEvent();
236     OnIsFocusActiveUpdate(false);
237 }
238 
AddIsFocusActiveUpdateEvent()239 void RadioPattern::AddIsFocusActiveUpdateEvent()
240 {
241     if (!isFocusActiveUpdateEvent_) {
242         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
243             auto pattern = weak.Upgrade();
244             CHECK_NULL_VOID(pattern);
245             pattern->OnIsFocusActiveUpdate(isFocusAcitve);
246         };
247     }
248 
249     auto pipline = PipelineContext::GetCurrentContext();
250     CHECK_NULL_VOID(pipline);
251     pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
252 }
253 
RemoveIsFocusActiveUpdateEvent()254 void RadioPattern::RemoveIsFocusActiveUpdateEvent()
255 {
256     auto pipline = PipelineContext::GetCurrentContext();
257     CHECK_NULL_VOID(pipline);
258     pipline->RemoveIsFocusActiveUpdateEvent(GetHost());
259 }
260 
OnIsFocusActiveUpdate(bool isFocusAcitve)261 void RadioPattern::OnIsFocusActiveUpdate(bool isFocusAcitve)
262 {
263     CHECK_NULL_VOID(radioModifier_);
264     radioModifier_->SetIsFocused(isFocusAcitve);
265 }
266 
ImageNodeCreate()267 void RadioPattern::ImageNodeCreate()
268 {
269     auto host = GetHost();
270     CHECK_NULL_VOID(host);
271     auto childNode = DynamicCast<FrameNode>(host->GetFirstChild());
272     if (preTypeIsBuilder_) {
273         host->RemoveChild(childNode);
274     }
275     if (!childNode || preTypeIsBuilder_) {
276         auto node = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
277             []() { return AceType::MakeRefPtr<ImagePattern>(); });
278         CHECK_NULL_VOID(node);
279         builderChildNode_ = AceType::DynamicCast<FrameNode>(node);
280         CHECK_NULL_VOID(builderChildNode_);
281         auto gesturehub = builderChildNode_->GetOrCreateGestureEventHub();
282         CHECK_NULL_VOID(gesturehub);
283         gesturehub->SetHitTestMode(HitTestMode::HTMNONE);
284     }
285     CHECK_NULL_VOID(builderChildNode_);
286     auto radioPaintProperty = host->GetPaintProperty<RadioPaintProperty>();
287     CHECK_NULL_VOID(radioPaintProperty);
288     auto imageProperty = builderChildNode_->GetLayoutProperty<ImageLayoutProperty>();
289     CHECK_NULL_VOID(imageProperty);
290     auto* pipeline = host->GetContext();
291     CHECK_NULL_VOID(pipeline);
292     auto radioTheme = pipeline->GetTheme<RadioTheme>();
293     CHECK_NULL_VOID(radioTheme);
294     imageProperty->UpdateUserDefinedIdealSize(GetChildContentSize(radioTheme));
295     auto imageSourceInfo = GetImageSourceInfoFromTheme(radioPaintProperty->GetRadioIndicator().value_or(0), radioTheme);
296     UpdateInternalResource(imageSourceInfo);
297     auto indicatorColor = radioPaintProperty->GetRadioIndicatorColor().value_or(Color(radioTheme->GetPointColor()));
298     auto imageRenderProperty = builderChildNode_->GetPaintProperty<ImageRenderProperty>();
299     CHECK_NULL_VOID(imageRenderProperty);
300     imageRenderProperty->UpdateSvgFillColor(indicatorColor);
301     imageProperty->UpdateImageSourceInfo(imageSourceInfo);
302     preTypeIsBuilder_ = false;
303     builderChildNode_->MountToParent(host);
304     builderChildNode_->MarkModifyDone();
305     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
306 }
307 
SetAccessibilityAction()308 void RadioPattern::SetAccessibilityAction()
309 {
310     auto host = GetHost();
311     CHECK_NULL_VOID(host);
312     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
313     CHECK_NULL_VOID(accessibilityProperty);
314     accessibilityProperty->SetActionSelect([weakPtr = WeakClaim(this)]() {
315         const auto& pattern = weakPtr.Upgrade();
316         CHECK_NULL_VOID(pattern);
317         pattern->UpdateSelectStatus(true);
318     });
319 
320     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
321         const auto& pattern = weakPtr.Upgrade();
322         CHECK_NULL_VOID(pattern);
323         pattern->UpdateSelectStatus(false);
324     });
325 }
326 
UpdateSelectStatus(bool isSelected)327 void RadioPattern::UpdateSelectStatus(bool isSelected)
328 {
329     auto host = GetHost();
330     CHECK_NULL_VOID(host);
331     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d update status %d", host->GetId(), isSelected);
332     auto context = host->GetRenderContext();
333     CHECK_NULL_VOID(context);
334     MarkIsSelected(isSelected);
335     context->OnMouseSelectUpdate(isSelected, ITEM_FILL_COLOR, ITEM_FILL_COLOR);
336 }
337 
MarkIsSelected(bool isSelected)338 void RadioPattern::MarkIsSelected(bool isSelected)
339 {
340     if (preCheck_ == isSelected) {
341         return;
342     }
343     preCheck_ = isSelected;
344     auto eventHub = GetOrCreateEventHub<RadioEventHub>();
345     CHECK_NULL_VOID(eventHub);
346     eventHub->UpdateChangeEvent(isSelected);
347     auto host = GetHost();
348     CHECK_NULL_VOID(host);
349     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d fire change event %{public}d", host->GetId(),
350         isSelected);
351     if (isSelected) {
352         eventHub->UpdateCurrentUIState(UI_STATE_SELECTED);
353         host->OnAccessibilityEvent(AccessibilityEventType::SELECTED);
354     } else {
355         eventHub->ResetCurrentUIState(UI_STATE_SELECTED);
356         host->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
357     }
358 }
359 
OnAfterModifyDone()360 void RadioPattern::OnAfterModifyDone()
361 {
362     auto host = GetHost();
363     CHECK_NULL_VOID(host);
364     auto inspectorId = host->GetInspectorId().value_or("");
365     if (inspectorId.empty()) {
366         return;
367     }
368     auto eventHub = host->GetOrCreateEventHub<RadioEventHub>();
369     CHECK_NULL_VOID(eventHub);
370     Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, eventHub->GetValue(), preCheck_);
371 }
372 
InitClickEvent()373 void RadioPattern::InitClickEvent()
374 {
375     if (clickListener_) {
376         return;
377     }
378     auto host = GetHost();
379     CHECK_NULL_VOID(host);
380     auto gesture = host->GetOrCreateGestureEventHub();
381     CHECK_NULL_VOID(gesture);
382     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
383         auto radioPattern = weak.Upgrade();
384         CHECK_NULL_VOID(radioPattern);
385         radioPattern->OnClick();
386     };
387     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
388     gesture->AddClickEvent(clickListener_);
389 }
390 
InitTouchEvent()391 void RadioPattern::InitTouchEvent()
392 {
393     if (UseContentModifier()) {
394         return;
395     }
396     if (touchListener_) {
397         return;
398     }
399     auto host = GetHost();
400     CHECK_NULL_VOID(host);
401     auto gesture = host->GetOrCreateGestureEventHub();
402     CHECK_NULL_VOID(gesture);
403     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
404         auto radioPattern = weak.Upgrade();
405         CHECK_NULL_VOID(radioPattern);
406         if (info.GetTouches().empty()) {
407             return;
408         }
409         if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
410             radioPattern->OnTouchDown();
411         }
412         if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
413             info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
414             radioPattern->OnTouchUp();
415         }
416     };
417     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
418     gesture->AddTouchEvent(touchListener_);
419 }
420 
InitMouseEvent()421 void RadioPattern::InitMouseEvent()
422 {
423     if (UseContentModifier()) {
424         return;
425     }
426     if (mouseEvent_) {
427         return;
428     }
429     auto host = GetHost();
430     CHECK_NULL_VOID(host);
431     auto gesture = host->GetOrCreateGestureEventHub();
432     CHECK_NULL_VOID(gesture);
433     auto eventHub = host->GetOrCreateEventHub<RadioEventHub>();
434     auto inputHub = eventHub->GetOrCreateInputEventHub();
435 
436     auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
437         auto pattern = weak.Upgrade();
438         if (pattern) {
439             pattern->HandleMouseEvent(isHover);
440         }
441     };
442     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
443     inputHub->AddOnHoverEvent(mouseEvent_);
444 }
445 
HandleMouseEvent(bool isHover)446 void RadioPattern::HandleMouseEvent(bool isHover)
447 {
448     if (UseContentModifier()) {
449         return;
450     }
451     isHover_ = isHover;
452     if (isHover) {
453         touchHoverType_ = TouchHoverAnimationType::HOVER;
454     } else {
455         touchHoverType_ = TouchHoverAnimationType::NONE;
456     }
457     auto host = GetHost();
458     CHECK_NULL_VOID(host);
459     TAG_LOGD(
460         AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d handle mouse hover %{public}d", host->GetId(), isHover);
461     host->MarkNeedRenderOnly();
462 }
463 
OnClick()464 void RadioPattern::OnClick()
465 {
466     if (UseContentModifier()) {
467         return;
468     }
469     auto host = GetHost();
470     CHECK_NULL_VOID(host);
471     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d handle click event", host->GetId());
472     auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
473     CHECK_NULL_VOID(paintProperty);
474     bool check = false;
475     if (paintProperty->HasRadioCheck()) {
476         check = paintProperty->GetRadioCheckValue();
477     } else {
478         paintProperty->UpdateRadioCheck(false);
479     }
480     if (!preCheck_ && !check) {
481         paintProperty->UpdateRadioCheck(true);
482         UpdateState();
483     }
484 }
485 
OnTouchDown()486 void RadioPattern::OnTouchDown()
487 {
488     if (UseContentModifier()) {
489         return;
490     }
491     if (isHover_) {
492         touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
493     } else {
494         touchHoverType_ = TouchHoverAnimationType::PRESS;
495     }
496     auto host = GetHost();
497     CHECK_NULL_VOID(host);
498     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d onTouch Down", host->GetId());
499     isTouch_ = true;
500     host->MarkNeedRenderOnly();
501 }
502 
OnTouchUp()503 void RadioPattern::OnTouchUp()
504 {
505     if (UseContentModifier()) {
506         return;
507     }
508     if (isHover_) {
509         touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
510     } else {
511         touchHoverType_ = TouchHoverAnimationType::NONE;
512     }
513     auto host = GetHost();
514     CHECK_NULL_VOID(host);
515     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d onTouch Up", host->GetId());
516     isTouch_ = false;
517     host->MarkNeedRenderOnly();
518 }
519 
CheckPageNode()520 void RadioPattern::CheckPageNode()
521 {
522     if (Container::IsInSubContainer()) {
523         return;
524     }
525     auto host = GetHost();
526     CHECK_NULL_VOID(host);
527     auto prePageId = GetPrePageId();
528     auto pipelineContext = PipelineContext::GetCurrentContext();
529     CHECK_NULL_VOID(pipelineContext);
530     auto stageManager = pipelineContext->GetStageManager();
531     CHECK_NULL_VOID(stageManager);
532     auto pageNode = stageManager->GetPageById(host->GetPageId());
533     CHECK_NULL_VOID(pageNode);
534     if (pageNode->GetId() != prePageId) {
535         auto eventHub = host->GetOrCreateEventHub<RadioEventHub>();
536         CHECK_NULL_VOID(eventHub);
537         auto groupManager = GetGroupManager();
538         CHECK_NULL_VOID(groupManager);
539         auto group = eventHub->GetGroup();
540         groupManager->AddRadioToGroup(group, host->GetId());
541         auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
542         CHECK_NULL_VOID(paintProperty);
543         bool check = false;
544         if (paintProperty->HasRadioCheck()) {
545             check = paintProperty->GetRadioCheckValue();
546         }
547         UpdateGroupCheckStatus(host, groupManager, check);
548     }
549 }
550 
UpdateState()551 void RadioPattern::UpdateState()
552 {
553     auto host = GetHost();
554     CHECK_NULL_VOID(host);
555     auto eventHub = host->GetOrCreateEventHub<RadioEventHub>();
556     CHECK_NULL_VOID(eventHub);
557 
558     auto pipelineContext = PipelineContext::GetCurrentContext();
559     CHECK_NULL_VOID(pipelineContext);
560     auto groupManager = GetGroupManager();
561     CHECK_NULL_VOID(groupManager);
562     auto preGroup = GetPreGroup();
563     auto group = eventHub->GetGroup();
564     if (!preGroup.has_value()) {
565         groupManager->AddRadioToGroup(group, host->GetId());
566         SetPrePageIdToLastPageId();
567         auto callback = [weak = WeakClaim(this)]() {
568             auto radio = weak.Upgrade();
569             if (radio) {
570                 radio->CheckPageNode();
571             }
572         };
573         pipelineContext->AddBuildFinishCallBack(callback);
574     }
575     if (preGroup.has_value() && preGroup.value() != group) {
576         groupManager->RemoveRadioFromGroup(preGroup.value(), host->GetId());
577         groupManager->AddRadioToGroup(group, host->GetId());
578         SetPrePageIdToLastPageId();
579         isGroupChanged_ = true;
580     }
581     SetPreGroup(group);
582 
583     auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
584     CHECK_NULL_VOID(paintProperty);
585 
586     bool check = false;
587     if (paintProperty->HasRadioCheck()) {
588         check = paintProperty->GetRadioCheckValue();
589         /*
590          * Do not set isFirstCreated_ to false if the radio is set to true at creation time. The isFirstCreated_ is set
591          * to false in UpdateGroupCheckStatus because isFirstCreated_ is also required to determine if an onChange event
592          * needs to be triggered.
593          */
594         if (check) {
595             UpdateUIStatus(true);
596             isOnAnimationFlag_ = true;
597         } else {
598             // If the radio is set to false, set isFirstCreated_ to false.
599             isFirstCreated_ = false;
600         }
601     } else {
602         paintProperty->UpdateRadioCheck(false);
603         // If the radio check is not set, set isFirstCreated_ to false.
604         isFirstCreated_ = false;
605     }
606     if (preCheck_ != check || isGroupChanged_) {
607         UpdateGroupCheckStatus(host, groupManager, check);
608     }
609     preCheck_ = check;
610     isGroupChanged_ = false;
611 }
612 
UpdateUncheckStatus(const RefPtr<FrameNode> & frameNode)613 void RadioPattern::UpdateUncheckStatus(const RefPtr<FrameNode>& frameNode)
614 {
615     auto radioPaintProperty = frameNode->GetPaintProperty<RadioPaintProperty>();
616     CHECK_NULL_VOID(radioPaintProperty);
617     if (radioPaintProperty->GetRadioCheckValue(false)) {
618         radioPaintProperty->UpdateRadioCheck(false);
619         FireBuilder();
620     }
621     frameNode->MarkNeedRenderOnly();
622     if (frameNode->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
623         startExitAnimation();
624     }
625     if (preCheck_) {
626         auto radioEventHub = GetOrCreateEventHub<RadioEventHub>();
627         CHECK_NULL_VOID(radioEventHub);
628         TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d fire unselect event", frameNode->GetId());
629         radioEventHub->UpdateChangeEvent(false);
630         isOnAnimationFlag_ = false;
631     }
632     preCheck_ = false;
633 }
634 
startEnterAnimation()635 void RadioPattern::startEnterAnimation()
636 {
637     auto host = GetHost();
638     CHECK_NULL_VOID(host);
639     auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATINGSPRING_VELOCITY,
640         DEFAULT_INTERPOLATINGSPRING_MASS, DEFAULT_INTERPOLATINGSPRING_STIFFNESS, DEFAULT_INTERPOLATINGSPRING_DAMPING);
641     AnimationOption delayOption;
642 
643     auto pipeline = host->GetContextRefPtr();
644     CHECK_NULL_VOID(pipeline);
645     auto radioTheme = pipeline->GetTheme<RadioTheme>();
646     CHECK_NULL_VOID(radioTheme);
647     if (radioTheme->IsCircleDial()) {
648         delayOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
649         delayOption.SetDelay(DEFAULT_RADIO_ANIMATION_DURATION_CIRCLE);
650     } else {
651         delayOption.SetCurve(springCurve);
652         delayOption.SetDelay(DEFAULT_RADIO_ANIMATION_DURATION);
653     }
654 
655     CHECK_NULL_VOID(builderChildNode_);
656     auto renderContext = builderChildNode_->GetRenderContext();
657     CHECK_NULL_VOID(renderContext);
658     renderContext->UpdateOpacity(INDICATOR_MIN_OPACITY);
659     renderContext->UpdateTransformScale({ INDICATOR_MIN_SCALE, INDICATOR_MIN_SCALE });
660     auto layoutProperty = builderChildNode_->GetLayoutProperty();
661     CHECK_NULL_VOID(layoutProperty);
662     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
663     auto eventHub = builderChildNode_->GetOrCreateEventHub<EventHub>();
664     if (eventHub) {
665         eventHub->SetEnabled(true);
666     }
667     AnimationUtils::Animate(
668         delayOption,
669         [&]() {
670             renderContext->UpdateTransformScale({ INDICATOR_MAX_SCALE, INDICATOR_MAX_SCALE });
671             renderContext->UpdateOpacity(INDICATOR_MAX_OPACITY);
672         },
673         nullptr, nullptr, pipeline);
674 }
675 
startExitAnimation()676 void RadioPattern::startExitAnimation()
677 {
678     auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(DEFAULT_INTERPOLATINGSPRING_VELOCITY,
679         DEFAULT_INTERPOLATINGSPRING_MASS, DEFAULT_INTERPOLATINGSPRING_STIFFNESS, DEFAULT_INTERPOLATINGSPRING_DAMPING);
680     AnimationOption delayOption;
681 
682     auto host = GetHost();
683     CHECK_NULL_VOID(host);
684     auto pipeline = host->GetContextRefPtr();
685     CHECK_NULL_VOID(pipeline);
686     auto radioTheme = pipeline->GetTheme<RadioTheme>();
687     CHECK_NULL_VOID(radioTheme);
688     if (radioTheme->IsCircleDial()) {
689         delayOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
690         delayOption.SetDelay(DEFAULT_RADIO_ANIMATION_DURATION_CIRCLE);
691     } else {
692         delayOption.SetCurve(springCurve);
693     }
694 
695     CHECK_NULL_VOID(builderChildNode_);
696     auto renderContext = builderChildNode_->GetRenderContext();
697     CHECK_NULL_VOID(renderContext);
698     AnimationUtils::Animate(
699         delayOption,
700         [&]() {
701             renderContext->UpdateTransformScale({ INDICATOR_MIN_SCALE, INDICATOR_MIN_SCALE });
702             renderContext->UpdateOpacity(INDICATOR_MIN_OPACITY);
703         },
704         nullptr, nullptr, pipeline);
705     auto eventHub = builderChildNode_->GetOrCreateEventHub<EventHub>();
706     if (eventHub) {
707         eventHub->SetEnabled(false);
708     }
709 }
710 
GetImageSourceInfoFromTheme(int32_t RadioIndicator,const RefPtr<RadioTheme> & radioTheme)711 ImageSourceInfo RadioPattern::GetImageSourceInfoFromTheme(int32_t RadioIndicator, const RefPtr<RadioTheme>& radioTheme)
712 {
713     ImageSourceInfo imageSourceInfo;
714     CHECK_NULL_RETURN(radioTheme, imageSourceInfo);
715     switch (RadioIndicator) {
716         case static_cast<int32_t>(RadioIndicatorType::TICK):
717             imageSourceInfo.SetResourceId(radioTheme->GetTickResourceId());
718             break;
719         case static_cast<int32_t>(RadioIndicatorType::DOT):
720             imageSourceInfo.SetResourceId(radioTheme->GetDotResourceId());
721             break;
722         default:
723             imageSourceInfo.SetResourceId(radioTheme->GetTickResourceId());
724             break;
725     }
726     return imageSourceInfo;
727 }
728 
UpdateInternalResource(ImageSourceInfo & sourceInfo)729 void RadioPattern::UpdateInternalResource(ImageSourceInfo& sourceInfo)
730 {
731     CHECK_NULL_VOID(sourceInfo.IsInternalResource());
732     auto host = GetHost();
733     CHECK_NULL_VOID(host);
734     auto* pipeline = host->GetContext();
735     CHECK_NULL_VOID(pipeline);
736     auto iconTheme = pipeline->GetTheme<IconTheme>();
737     CHECK_NULL_VOID(iconTheme);
738     auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
739     if (iconPath.empty()) {
740         return;
741     }
742     sourceInfo.SetSrc(iconPath);
743 }
744 
LoadBuilder()745 void RadioPattern::LoadBuilder()
746 {
747     RefPtr<UINode> customNode;
748     if (builder_) {
749         auto host = GetHost();
750         CHECK_NULL_VOID(host);
751         auto childNode = DynamicCast<FrameNode>(host->GetFirstChild());
752         if (preTypeIsBuilder_) {
753             return;
754         } else {
755             if (childNode) {
756                 host->RemoveChild(childNode);
757             }
758         }
759         NG::ScopedViewStackProcessor builderViewStackProcessor;
760         builder_();
761         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
762         CHECK_NULL_VOID(customNode);
763         builderChildNode_ = AceType::DynamicCast<FrameNode>(customNode);
764         CHECK_NULL_VOID(builderChildNode_);
765         preTypeIsBuilder_ = true;
766         builderChildNode_->MountToParent(host);
767         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
768     }
769 }
770 
GetChildContentSize(const RefPtr<RadioTheme> & radioTheme)771 CalcSize RadioPattern::GetChildContentSize(const RefPtr<RadioTheme>& radioTheme)
772 {
773     CHECK_NULL_RETURN(radioTheme, CalcSize());
774     auto host = GetHost();
775     CHECK_NULL_RETURN(host, CalcSize());
776     auto layoutProperty = host->GetLayoutProperty<LayoutProperty>();
777     CHECK_NULL_RETURN(layoutProperty, CalcSize());
778     auto &&layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
779     if (layoutConstraint && layoutConstraint->selfIdealSize) {
780         auto selfIdealSize = layoutConstraint->selfIdealSize;
781         if (selfIdealSize->IsValid()) {
782             auto height = selfIdealSize->Height()->GetDimension() * DEFAULT_RADIO_IMAGE_SCALE;
783             auto width = selfIdealSize->Width()->GetDimension() * DEFAULT_RADIO_IMAGE_SCALE;
784             auto length = std::min(width, height);
785             return CalcSize(NG::CalcLength(length), NG::CalcLength(length));
786         }
787         if (selfIdealSize->Width().has_value()) {
788             auto width = selfIdealSize->Width()->GetDimension() * DEFAULT_RADIO_IMAGE_SCALE;
789             return CalcSize(NG::CalcLength(width), NG::CalcLength(width));
790         }
791         if (selfIdealSize->Height().has_value()) {
792             auto height = selfIdealSize->Height()->GetDimension() * DEFAULT_RADIO_IMAGE_SCALE;
793             return CalcSize(NG::CalcLength(height), NG::CalcLength(height));
794         }
795     }
796     Dimension defaultWidth = radioTheme->GetWidth();
797     Dimension defaultHeight = radioTheme->GetHeight();
798     Dimension horizontalPadding = radioTheme->GetDefaultPaddingSize();
799     Dimension verticalPadding = radioTheme->GetDefaultPaddingSize();
800     auto width = (defaultWidth - horizontalPadding * RADIO_PADDING_COUNT) * DEFAULT_RADIO_IMAGE_SCALE;
801     auto height = (defaultHeight - verticalPadding * RADIO_PADDING_COUNT) * DEFAULT_RADIO_IMAGE_SCALE;
802     return CalcSize(NG::CalcLength(width), NG::CalcLength(height));
803 }
804 
UpdateGroupCheckStatus(const RefPtr<FrameNode> & frameNode,const RefPtr<GroupManager> & groupManager,bool check)805 void RadioPattern::UpdateGroupCheckStatus(
806     const RefPtr<FrameNode>& frameNode, const RefPtr<GroupManager>& groupManager, bool check)
807 {
808     frameNode->MarkNeedRenderOnly();
809     if (frameNode->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
810         if (!isFirstCreated_ && check) {
811             startEnterAnimation();
812         }
813     }
814 
815     auto radioEventHub = GetOrCreateEventHub<RadioEventHub>();
816     CHECK_NULL_VOID(radioEventHub);
817     if (check) {
818         groupManager->UpdateRadioGroupValue(radioEventHub->GetGroup(), frameNode->GetId());
819     } else {
820         auto radioPaintProperty = frameNode->GetPaintProperty<RadioPaintProperty>();
821         CHECK_NULL_VOID(radioPaintProperty);
822         radioPaintProperty->UpdateRadioCheck(check);
823         if (!isGroupChanged_) {
824             isOnAnimationFlag_ = false;
825         }
826     }
827 
828     if (!isFirstCreated_) {
829         TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "radio node %{public}d fire group change event %{public}d",
830             frameNode->GetId(), check);
831         radioEventHub->UpdateChangeEvent(check);
832     }
833 }
834 
UpdateUIStatus(bool check)835 void RadioPattern::UpdateUIStatus(bool check)
836 {
837     uiStatus_ = check ? UIStatus::SELECTED : UIStatus::UNSELECTED;
838     auto host = GetHost();
839     CHECK_NULL_VOID(host);
840     host->MarkNeedRenderOnly();
841 }
842 
OnKeyEvent(const KeyEvent & event)843 bool RadioPattern::OnKeyEvent(const KeyEvent& event)
844 {
845     if (event.action == KeyAction::DOWN && event.code == KeyCode::KEY_FUNCTION) {
846         OnClick();
847         return true;
848     }
849     return false;
850 }
851 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)852 void RadioPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
853 {
854     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
855         auto pattern = wp.Upgrade();
856         if (pattern) {
857             pattern->GetInnerFocusPaintRect(paintRect);
858         }
859     };
860     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
861 
862     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
863         auto pattern = wp.Upgrade();
864         if (pattern) {
865             return pattern->OnKeyEvent(event);
866         } else {
867             return false;
868         }
869     };
870     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
871 }
872 
GetInnerFocusPaintRect(RoundRect & paintRect)873 void RadioPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
874 {
875     auto host = GetHost();
876     CHECK_NULL_VOID(host);
877     auto* pipeline = host->GetContext();
878     CHECK_NULL_VOID(pipeline);
879     auto radioTheme = pipeline->GetTheme<RadioTheme>();
880     CHECK_NULL_VOID(radioTheme);
881     auto focusPaintPadding = radioTheme->GetFocusPaintPadding().ConvertToPx();
882     float outCircleRadius = size_.Width() / 2 + focusPaintPadding;
883     float originX = offset_.GetX() - focusPaintPadding;
884     float originY = offset_.GetY() - focusPaintPadding;
885     float width = size_.Width() + 2 * focusPaintPadding;
886     float height = size_.Height() + 2 * focusPaintPadding;
887     paintRect.SetRect({ originX, originY, width, height });
888     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, outCircleRadius, outCircleRadius);
889     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, outCircleRadius, outCircleRadius);
890     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, outCircleRadius, outCircleRadius);
891     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, outCircleRadius, outCircleRadius);
892 }
893 
GetFocusPattern() const894 FocusPattern RadioPattern::GetFocusPattern() const
895 {
896     auto host = GetHost();
897     CHECK_NULL_RETURN(host, FocusPattern());
898     auto pipeline = host->GetContext();
899     CHECK_NULL_RETURN(pipeline, FocusPattern());
900     auto radioTheme = pipeline->GetTheme<RadioTheme>();
901     CHECK_NULL_RETURN(radioTheme, FocusPattern());
902     FocusPaintParam focusPaintParam;
903     if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
904         auto focusColor = radioTheme->GetFocusColor();
905         focusPaintParam.SetPaintColor(focusColor);
906     } else {
907         auto activeColor = radioTheme->GetActiveColor();
908         focusPaintParam.SetPaintColor(activeColor);
909     }
910     return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
911 }
912 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig &)913 bool RadioPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& /*config*/)
914 {
915     auto geometryNode = dirty->GetGeometryNode();
916     offset_ = geometryNode->GetContentOffset();
917     size_ = geometryNode->GetContentSize();
918     if (!isUserSetResponseRegion_) {
919         AddHotZoneRect();
920     }
921     return true;
922 }
923 
924 // Set the default hot zone for the component.
AddHotZoneRect()925 void RadioPattern::AddHotZoneRect()
926 {
927     hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
928     hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
929     hotZoneSize_.SetWidth(
930         size_.Width() + FOR_HOTZONESIZE_CALCULATE_MULTIPLY_TWO * hotZoneHorizontalPadding_.ConvertToPx());
931     hotZoneSize_.SetHeight(
932         size_.Height() + FOR_HOTZONESIZE_CALCULATE_MULTIPLY_TWO * hotZoneVerticalPadding_.ConvertToPx());
933     DimensionRect hotZoneRegion;
934     hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
935     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
936     auto host = GetHost();
937     CHECK_NULL_VOID(host);
938     auto gestureHub = host->GetOrCreateGestureEventHub();
939     CHECK_NULL_VOID(gestureHub);
940     gestureHub->SetResponseRegion(std::vector<DimensionRect>({ hotZoneRegion }));
941 }
942 
RemoveLastHotZoneRect() const943 void RadioPattern::RemoveLastHotZoneRect() const
944 {
945     auto host = GetHost();
946     CHECK_NULL_VOID(host);
947     host->RemoveLastHotZoneRect();
948 }
949 
ProvideRestoreInfo()950 std::string RadioPattern::ProvideRestoreInfo()
951 {
952     auto jsonObj = JsonUtil::Create(true);
953     auto radioPaintProperty = GetPaintProperty<RadioPaintProperty>();
954     CHECK_NULL_RETURN(radioPaintProperty, "");
955     jsonObj->Put("checked", radioPaintProperty->GetRadioCheck().value_or(false));
956     return jsonObj->ToString();
957 }
958 
OnRestoreInfo(const std::string & restoreInfo)959 void RadioPattern::OnRestoreInfo(const std::string& restoreInfo)
960 {
961     auto radioPaintProperty = GetPaintProperty<RadioPaintProperty>();
962     CHECK_NULL_VOID(radioPaintProperty);
963     auto info = JsonUtil::ParseJsonString(restoreInfo);
964     if (!info->IsValid() || !info->IsObject()) {
965         return;
966     }
967     auto jsonChecked = info->GetValue("checked");
968     radioPaintProperty->UpdateRadioCheck(jsonChecked->GetBool());
969     OnModifyDone();
970 }
971 
HandleEnabled()972 void RadioPattern::HandleEnabled()
973 {
974     auto host = GetHost();
975     CHECK_NULL_VOID(host);
976     auto eventHub = host->GetOrCreateEventHub<EventHub>();
977     CHECK_NULL_VOID(eventHub);
978     auto enabled = eventHub->IsEnabled();
979     auto radioPaintProperty = GetHost()->GetPaintProperty<RadioPaintProperty>();
980     if (enabled_ != enabled) {
981         enabled_ = enabled;
982         if (!enabled_ && host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
983             if (!radioModifier_) {
984                 radioModifier_ = AceType::MakeRefPtr<RadioModifier>();
985             }
986             if (!radioPaintProperty->HasRadioCheck() || !radioPaintProperty->GetRadioCheckValue()) {
987                 radioModifier_->SetUIStatus(UIStatus::UNSELECTED);
988             }
989         }
990         auto paintProperty = GetPaintProperty<RadioPaintProperty>();
991         CHECK_NULL_VOID(paintProperty);
992         paintProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
993     }
994 }
995 
SetRadioChecked(bool check)996 void RadioPattern::SetRadioChecked(bool check)
997 {
998     auto host = GetHost();
999     CHECK_NULL_VOID(host);
1000     auto eventHub = host->GetOrCreateEventHub<EventHub>();
1001     CHECK_NULL_VOID(eventHub);
1002     auto enabled = eventHub->IsEnabled();
1003     if (!enabled) {
1004         return;
1005     }
1006     auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
1007     CHECK_NULL_VOID(paintProperty);
1008     paintProperty->UpdateRadioCheck(check);
1009     UpdateState();
1010     OnModifyDone();
1011 }
1012 
DumpInfo()1013 void RadioPattern::DumpInfo ()
1014 {
1015     auto eventHub = GetOrCreateEventHub<RadioEventHub>();
1016     CHECK_NULL_VOID(eventHub);
1017     DumpLog::GetInstance().AddDesc("Value: " + eventHub->GetValue());
1018     DumpLog::GetInstance().AddDesc("Group: " + eventHub->GetGroup());
1019 
1020     auto paintProperty = GetPaintProperty<RadioPaintProperty>();
1021     CHECK_NULL_VOID(paintProperty);
1022     if (paintProperty->HasRadioIndicator()) {
1023         DumpLog::GetInstance().AddDesc("IndicatorType: " + std::to_string(paintProperty->GetRadioIndicatorValue()));
1024     }
1025     if (paintProperty->HasRadioCheck()) {
1026         DumpLog::GetInstance().AddDesc(
1027             "IsChecked: " + std::string(paintProperty->GetRadioCheckValue() ? "true" : "false"));
1028     }
1029     if (paintProperty->HasRadioCheckedBackgroundColor()) {
1030         DumpLog::GetInstance().AddDesc(
1031             "CheckedBackgroundColor: " + paintProperty->GetRadioCheckedBackgroundColorValue().ToString());
1032     }
1033     if (paintProperty->HasRadioUncheckedBorderColor()) {
1034         DumpLog::GetInstance().AddDesc(
1035             "UncheckedBorderColor: " + paintProperty->GetRadioUncheckedBorderColorValue().ToString());
1036     }
1037     if (paintProperty->HasRadioIndicatorColor()) {
1038         DumpLog::GetInstance().AddDesc("IndicatorColor: " + paintProperty->GetRadioIndicatorColorValue().ToString());
1039     }
1040 }
1041 
UpdateRadioComponentColor(const Color & color,const RadioColorType radioColorType)1042 void RadioPattern::UpdateRadioComponentColor(const Color& color, const RadioColorType radioColorType)
1043 {
1044     auto host = GetHost();
1045     CHECK_NULL_VOID(host);
1046     auto pipelineContext = host->GetContext();
1047     CHECK_NULL_VOID(pipelineContext);
1048     auto paintProperty = GetPaintProperty<RadioPaintProperty>();
1049     CHECK_NULL_VOID(paintProperty);
1050     switch (radioColorType) {
1051         case RadioColorType::CHECKED_BACKGROUND_COLOR:
1052             paintProperty->UpdateRadioCheckedBackgroundColor(color);
1053             break;
1054         case RadioColorType::UNCHECKED_BORDER_COLOR:
1055             paintProperty->UpdateRadioUncheckedBorderColor(color);
1056             break;
1057         case RadioColorType::INDICATOR_COLOR:
1058             paintProperty->UpdateRadioIndicatorColor(color);
1059             ImageNodeCreate();
1060             break;
1061         default:
1062             break;
1063     }
1064     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1065 }
1066 
FireBuilder()1067 void RadioPattern::FireBuilder()
1068 {
1069     auto host = GetHost();
1070     CHECK_NULL_VOID(host);
1071     if (!makeFunc_.has_value()) {
1072         host->RemoveChildAndReturnIndex(customNode_);
1073         customNode_ = nullptr;
1074         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1075         return;
1076     }
1077     auto node = BuildContentModifierNode();
1078     if (customNode_ == node) {
1079         return;
1080     }
1081     host->RemoveChildAndReturnIndex(customNode_);
1082     customNode_ = node;
1083     CHECK_NULL_VOID(customNode_);
1084     host->AddChild(customNode_, 0);
1085     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1086 }
1087 
BuildContentModifierNode()1088 RefPtr<FrameNode> RadioPattern::BuildContentModifierNode()
1089 {
1090     CHECK_NULL_RETURN(makeFunc_, nullptr);
1091     auto host = GetHost();
1092     CHECK_NULL_RETURN(host, nullptr);
1093     auto eventHub = host->GetOrCreateEventHub<RadioEventHub>();
1094     CHECK_NULL_RETURN(eventHub, nullptr);
1095     auto value = eventHub->GetValue();
1096     auto enabled = eventHub->IsEnabled();
1097     auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
1098     CHECK_NULL_RETURN(paintProperty, nullptr);
1099     bool isChecked = false;
1100     if (paintProperty->HasRadioCheck()) {
1101         isChecked = paintProperty->GetRadioCheckValue();
1102     } else {
1103         isChecked = false;
1104     }
1105     RadioConfiguration radioConfiguration(value, isChecked, enabled);
1106     return (makeFunc_.value())(radioConfiguration);
1107 }
1108 
GetGroupManager()1109 RefPtr<GroupManager> RadioPattern::GetGroupManager()
1110 {
1111     auto manager = groupManager_.Upgrade();
1112     if (manager) {
1113         return manager;
1114     }
1115     groupManager_ = GroupManager::GetGroupManager();
1116     return groupManager_.Upgrade();
1117 }
1118 
SetPrePageIdToLastPageId()1119 void RadioPattern::SetPrePageIdToLastPageId()
1120 {
1121     if (!Container::IsInSubContainer()) {
1122         auto pipelineContext = PipelineContext::GetCurrentContext();
1123         CHECK_NULL_VOID(pipelineContext);
1124         auto stageManager = pipelineContext->GetStageManager();
1125         CHECK_NULL_VOID(stageManager);
1126         auto pageNode = stageManager->GetLastPage();
1127         CHECK_NULL_VOID(pageNode);
1128         SetPrePageId(pageNode->GetId());
1129     }
1130 }
1131 
OnColorConfigurationUpdate()1132 void RadioPattern::OnColorConfigurationUpdate()
1133 {
1134     if (!SystemProperties::ConfigChangePerform()) {
1135         return;
1136     }
1137     auto host = GetHost();
1138     CHECK_NULL_VOID(host);
1139     auto paintProperty = host->GetPaintProperty<RadioPaintProperty>();
1140     CHECK_NULL_VOID(paintProperty);
1141     auto pipeline = host->GetContext();
1142     CHECK_NULL_VOID(pipeline);
1143     auto radioTheme = pipeline->GetTheme<RadioTheme>();
1144     CHECK_NULL_VOID(radioTheme);
1145     auto pattern = host->GetPattern<RadioPattern>();
1146     CHECK_NULL_VOID(pattern);
1147 
1148     if (!paintProperty->GetRadioCheckedBackgroundColorSetByUser().value_or(false)) {
1149         auto activeColor = radioTheme->GetActiveColor();
1150         paintProperty->UpdateRadioCheckedBackgroundColor(activeColor);
1151     }
1152     if (!paintProperty->GetRadioUncheckedBorderColorSetByUser().value_or(false)) {
1153         Color inActiveColor;
1154         if (pattern->GetUncheckedBorderColorByJSRadioTheme()) {
1155             inActiveColor = radioTheme->GetInactiveColor();
1156         } else {
1157             inActiveColor = radioTheme->GetUnCheckBorderColor();
1158         }
1159         paintProperty->UpdateRadioUncheckedBorderColor(inActiveColor);
1160     }
1161     if (!paintProperty->GetRadioIndicatorColorSetByUser().value_or(false)) {
1162         Color pointColor;
1163         if (pattern->GetIndicatorColorByJSRadioTheme()) {
1164             pointColor = radioTheme->GetPointColor();
1165             paintProperty->UpdateRadioIndicatorColor(pointColor);
1166         } else {
1167             paintProperty->UpdateRadioIndicatorColor(DEFAULT_INDICATOR_DARK_LIGHT_COLOR);
1168         }
1169         ImageNodeCreate();
1170     }
1171     host->MarkModifyDone();
1172     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1173 }
1174 } // namespace OHOS::Ace::NG
1175