• 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 "base/utils/multi_thread.h"
17 #include "core/components_ng/pattern/checkbox/checkbox_pattern.h"
18 
19 #include "base/log/dump_log.h"
20 #include "core/components/checkable/checkable_theme.h"
21 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_paint_property.h"
22 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_pattern.h"
23 #include "core/components_ng/pattern/stage/page_event_hub.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 
26 namespace OHOS::Ace::NG {
27 namespace {
28 const Color ITEM_FILL_COLOR = Color::TRANSPARENT;
29 constexpr int32_t DEFAULT_CHECKBOX_ANIMATION_DURATION = 100;
30 } // namespace
31 
CreateNodePaintMethod()32 RefPtr<NodePaintMethod> CheckBoxPattern::CreateNodePaintMethod()
33 {
34     auto host = GetHost();
35     CHECK_NULL_RETURN(host, nullptr);
36     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
37     paintProperty->SetHost(host);
38     if (!paintMethod_) {
39         paintMethod_ = MakeRefPtr<CheckBoxPaintMethod>();
40         paintMethod_->SetNeedAnimation(visible_);
41     }
42     CheckBoxStyle checkboxStyle = CheckBoxStyle::CIRCULAR_STYLE;
43     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
44         checkboxStyle = CheckBoxStyle::CIRCULAR_STYLE;
45     } else {
46         checkboxStyle = CheckBoxStyle::SQUARE_STYLE;
47     }
48     if (paintProperty->HasCheckBoxSelectedStyle()) {
49         checkboxStyle = paintProperty->GetCheckBoxSelectedStyleValue(CheckBoxStyle::CIRCULAR_STYLE);
50     }
51     paintMethod_->SetCheckboxStyle(checkboxStyle);
52     paintMethod_->SetUseContentModifier(UseContentModifier());
53     paintMethod_->SetHasBuilder(builder_.has_value());
54     host->SetCheckboxFlag(true);
55     auto eventHub = host->GetOrCreateEventHub<EventHub>();
56     CHECK_NULL_RETURN(eventHub, nullptr);
57     auto enabled = eventHub->IsEnabled();
58     paintMethod_->SetEnabled(enabled);
59     paintMethod_->SetTouchHoverAnimationType(touchHoverType_);
60     return paintMethod_;
61 }
62 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool,bool)63 bool CheckBoxPattern::OnDirtyLayoutWrapperSwap(
64     const RefPtr<LayoutWrapper>& dirty, bool /*skipMeasure*/, bool /*skipLayout*/)
65 {
66     auto geometryNode = dirty->GetGeometryNode();
67     offset_ = geometryNode->GetContentOffset();
68     size_ = geometryNode->GetContentSize();
69     if (!isUserSetResponseRegion_) {
70         AddHotZoneRect();
71     }
72     return true;
73 }
74 
SetBuilderFunc(CheckBoxMakeCallback && makeFunc)75 void CheckBoxPattern::SetBuilderFunc(CheckBoxMakeCallback&& makeFunc)
76 {
77     if (makeFunc == nullptr) {
78         makeFunc_ = std::nullopt;
79         OnModifyDone();
80         return;
81     }
82     makeFunc_ = std::move(makeFunc);
83 }
84 
SetToggleBuilderFunc(SwitchMakeCallback && toggleMakeFunc)85 void CheckBoxPattern::SetToggleBuilderFunc(SwitchMakeCallback&& toggleMakeFunc)
86 {
87     if (toggleMakeFunc == nullptr) {
88         toggleMakeFunc_ = std::nullopt;
89         OnModifyDone();
90         return;
91     }
92     toggleMakeFunc_ = std::move(toggleMakeFunc);
93 }
94 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const95 void CheckBoxPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
96 {
97     Pattern::ToJsonValue(json, filter);
98     /* no fixed attr below, just return */
99     if (filter.IsFastFilter()) {
100         return;
101     }
102     auto host = GetHost();
103     CHECK_NULL_VOID(host);
104     auto checkBoxEventHub = host->GetOrCreateEventHub<NG::CheckBoxEventHub>();
105     auto name = checkBoxEventHub ? checkBoxEventHub->GetName() : "";
106     auto group = checkBoxEventHub ? checkBoxEventHub->GetGroupName() : "";
107     json->PutExtAttr("name", name.c_str(), filter);
108     json->PutExtAttr("group", group.c_str(), filter);
109     json->PutExtAttr("type", "ToggleType.Checkbox", filter);
110     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
111     auto select = paintProperty->GetCheckBoxSelectValue(false);
112     json->PutExtAttr("select", select ? "true" : "false", filter);
113 }
114 
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const115 void CheckBoxPattern::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
116 {
117     Pattern::ToTreeJson(json, config);
118     auto host = GetHost();
119     CHECK_NULL_VOID(host);
120     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
121     CHECK_NULL_VOID(paintProperty);
122     auto select = paintProperty->GetCheckBoxSelectValue(false);
123     json->Put(TreeKey::CHECKED, select ? "true" : "false");
124 }
125 
OnAttachToFrameNode()126 void CheckBoxPattern::OnAttachToFrameNode()
127 {
128     auto host = GetHost();
129     CHECK_NULL_VOID(host);
130     THREAD_SAFE_NODE_CHECK(host, OnAttachToFrameNode, host);
131     host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
132 }
133 
SetBuilderNodeHidden()134 void CheckBoxPattern::SetBuilderNodeHidden()
135 {
136     CHECK_NULL_VOID(builderNode_);
137     auto layoutProperty = builderNode_->GetLayoutProperty();
138     CHECK_NULL_VOID(layoutProperty);
139     layoutProperty->UpdateVisibility(VisibleType::GONE);
140 }
141 
UpdateIndicator()142 void CheckBoxPattern::UpdateIndicator()
143 {
144     auto host = GetHost();
145     CHECK_NULL_VOID(host);
146     if (builder_.has_value() && !UseContentModifier()) {
147         LoadBuilder();
148         auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
149         CHECK_NULL_VOID(paintProperty);
150         bool isSelected = false;
151         if (paintProperty->HasCheckBoxSelect()) {
152             isSelected = paintProperty->GetCheckBoxSelectValue();
153             if (!isSelected) {
154                 SetBuilderNodeHidden();
155             }
156         } else {
157             SetBuilderNodeHidden();
158         }
159     } else if (builderNode_) {
160         host->RemoveChildAndReturnIndex(builderNode_);
161         builderNode_ = nullptr;
162     }
163 }
164 
OnModifyDone()165 void CheckBoxPattern::OnModifyDone()
166 {
167     Pattern::OnModifyDone();
168     FireBuilder();
169     UpdateIndicator();
170     UpdateState();
171     auto host = GetHost();
172     CHECK_NULL_VOID(host);
173     auto pipeline = GetContext();
174     CHECK_NULL_VOID(pipeline);
175     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>(host->GetThemeScopeId());
176     CHECK_NULL_VOID(checkBoxTheme);
177     hotZoneHorizontalPadding_ = checkBoxTheme->GetHotZoneHorizontalPadding();
178     hotZoneVerticalPadding_ = checkBoxTheme->GetHotZoneVerticalPadding();
179     InitDefaultMargin();
180     RegisterVisibleAreaChange();
181     InitClickEvent();
182     InitTouchEvent();
183     InitMouseEvent();
184     InitFocusEvent();
185     auto focusHub = host->GetFocusHub();
186     CHECK_NULL_VOID(focusHub);
187     InitOnKeyEvent(focusHub);
188     SetAccessibilityAction();
189 }
190 
InitDefaultMargin()191 void CheckBoxPattern::InitDefaultMargin()
192 {
193     if (makeFunc_.has_value() || toggleMakeFunc_.has_value()) {
194         ResetDefaultMargin();
195         return;
196     }
197     auto host = GetHost();
198     CHECK_NULL_VOID(host);
199     auto layoutProperty = host->GetLayoutProperty();
200     CHECK_NULL_VOID(layoutProperty);
201     MarginProperty margin;
202     margin.left = CalcLength(hotZoneHorizontalPadding_.Value());
203     margin.right = CalcLength(hotZoneHorizontalPadding_.Value());
204     margin.top = CalcLength(hotZoneVerticalPadding_.Value());
205     margin.bottom = CalcLength(hotZoneVerticalPadding_.Value());
206     auto& setMargin = layoutProperty->GetMarginProperty();
207     if (setMargin) {
208         if (setMargin->left.has_value()) {
209             margin.left = setMargin->left;
210         }
211         if (setMargin->right.has_value()) {
212             margin.right = setMargin->right;
213         }
214         if (setMargin->top.has_value()) {
215             margin.top = setMargin->top;
216         }
217         if (setMargin->bottom.has_value()) {
218             margin.bottom = setMargin->bottom;
219         }
220     }
221     layoutProperty->UpdateMargin(margin);
222 }
223 
ResetDefaultMargin()224 void CheckBoxPattern::ResetDefaultMargin()
225 {
226     if (isUserSetMargin_) {
227         return;
228     }
229     auto host = GetHost();
230     CHECK_NULL_VOID(host);
231     auto layoutProperty = host->GetLayoutProperty();
232     CHECK_NULL_VOID(layoutProperty);
233     MarginProperty margin;
234     layoutProperty->UpdateMargin(margin);
235 }
236 
SetAccessibilityAction()237 void CheckBoxPattern::SetAccessibilityAction()
238 {
239     auto host = GetHost();
240     CHECK_NULL_VOID(host);
241     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
242     CHECK_NULL_VOID(accessibilityProperty);
243     accessibilityProperty->SetActionSelect([weakPtr = WeakClaim(this)]() {
244         const auto& pattern = weakPtr.Upgrade();
245         CHECK_NULL_VOID(pattern);
246         pattern->UpdateSelectStatus(true);
247     });
248 
249     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
250         const auto& pattern = weakPtr.Upgrade();
251         CHECK_NULL_VOID(pattern);
252         pattern->UpdateSelectStatus(false);
253     });
254 }
255 
UpdateSelectStatus(bool isSelected)256 void CheckBoxPattern::UpdateSelectStatus(bool isSelected)
257 {
258     auto host = GetHost();
259     CHECK_NULL_VOID(host);
260     auto context = host->GetRenderContext();
261     CHECK_NULL_VOID(context);
262     MarkIsSelected(isSelected);
263     context->OnMouseSelectUpdate(isSelected, ITEM_FILL_COLOR, ITEM_FILL_COLOR);
264 }
265 
MarkIsSelected(bool isSelected)266 void CheckBoxPattern::MarkIsSelected(bool isSelected)
267 {
268     if (lastSelect_ == isSelected) {
269         return;
270     }
271     lastSelect_ = isSelected;
272     auto eventHub = GetOrCreateEventHub<CheckBoxEventHub>();
273     CHECK_NULL_VOID(eventHub);
274     eventHub->UpdateChangeEvent(isSelected);
275     auto host = GetHost();
276     CHECK_NULL_VOID(host);
277     if (isSelected) {
278         eventHub->UpdateCurrentUIState(UI_STATE_SELECTED);
279         host->OnAccessibilityEvent(AccessibilityEventType::SELECTED);
280     } else {
281         eventHub->ResetCurrentUIState(UI_STATE_SELECTED);
282         host->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
283     }
284 }
285 
OnAfterModifyDone()286 void CheckBoxPattern::OnAfterModifyDone()
287 {
288     auto host = GetHost();
289     CHECK_NULL_VOID(host);
290     auto inspectorId = host->GetInspectorId().value_or("");
291     if (inspectorId.empty()) {
292         return;
293     }
294     auto eventHub = host->GetOrCreateEventHub<CheckBoxEventHub>();
295     CHECK_NULL_VOID(eventHub);
296     Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, eventHub->GetName(), lastSelect_);
297 }
298 
InitClickEvent()299 void CheckBoxPattern::InitClickEvent()
300 {
301     if (clickListener_) {
302         return;
303     }
304     auto host = GetHost();
305     CHECK_NULL_VOID(host);
306     auto gesture = host->GetOrCreateGestureEventHub();
307     CHECK_NULL_VOID(gesture);
308     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
309         auto checkboxPattern = weak.Upgrade();
310         CHECK_NULL_VOID(checkboxPattern);
311         checkboxPattern->OnClick();
312     };
313     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
314     gesture->AddClickEvent(clickListener_);
315 }
316 
InitTouchEvent()317 void CheckBoxPattern::InitTouchEvent()
318 {
319     if (touchListener_) {
320         return;
321     }
322     auto host = GetHost();
323     CHECK_NULL_VOID(host);
324     auto gesture = host->GetOrCreateGestureEventHub();
325     CHECK_NULL_VOID(gesture);
326     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
327         auto checkboxPattern = weak.Upgrade();
328         CHECK_NULL_VOID(checkboxPattern);
329         if (info.GetTouches().empty()) {
330             return;
331         }
332         if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
333             checkboxPattern->OnTouchDown();
334         }
335         if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
336             info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
337             checkboxPattern->OnTouchUp();
338         }
339     };
340     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
341     gesture->AddTouchEvent(touchListener_);
342 }
343 
InitMouseEvent()344 void CheckBoxPattern::InitMouseEvent()
345 {
346     if (mouseEvent_) {
347         return;
348     }
349     auto host = GetHost();
350     CHECK_NULL_VOID(host);
351     auto gesture = host->GetOrCreateGestureEventHub();
352     CHECK_NULL_VOID(gesture);
353     auto eventHub = host->GetOrCreateEventHub<CheckBoxEventHub>();
354     auto inputHub = eventHub->GetOrCreateInputEventHub();
355 
356     auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
357         auto pattern = weak.Upgrade();
358         if (pattern) {
359             pattern->HandleMouseEvent(isHover);
360         }
361     };
362     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
363     inputHub->AddOnHoverEvent(mouseEvent_);
364 }
365 
HandleMouseEvent(bool isHover)366 void CheckBoxPattern::HandleMouseEvent(bool isHover)
367 {
368     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox on hover %{public}d", isHover);
369     isHover_ = isHover;
370     if (isHover) {
371         touchHoverType_ = TouchHoverAnimationType::HOVER;
372     } else {
373         touchHoverType_ = TouchHoverAnimationType::NONE;
374     }
375     auto host = GetHost();
376     CHECK_NULL_VOID(host);
377     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
378 }
379 
InitFocusEvent()380 void CheckBoxPattern::InitFocusEvent()
381 {
382     if (focusEventInitialized_) {
383         return;
384     }
385     auto host = GetHost();
386     CHECK_NULL_VOID(host);
387     auto focusHub = host->GetOrCreateFocusHub();
388     auto focusTask = [weak = WeakClaim(this)](FocusReason reason) {
389         auto pattern = weak.Upgrade();
390         CHECK_NULL_VOID(pattern);
391         pattern->HandleFocusEvent();
392     };
393     focusHub->SetOnFocusInternal(focusTask);
394     auto blurTask = [weak = WeakClaim(this)]() {
395         auto pattern = weak.Upgrade();
396         CHECK_NULL_VOID(pattern);
397         pattern->HandleBlurEvent();
398     };
399     focusHub->SetOnBlurInternal(blurTask);
400 
401     focusEventInitialized_ = true;
402 }
403 
HandleFocusEvent()404 void CheckBoxPattern::HandleFocusEvent()
405 {
406     CHECK_NULL_VOID(paintMethod_);
407     AddIsFocusActiveUpdateEvent();
408     OnIsFocusActiveUpdate(true);
409 }
410 
HandleBlurEvent()411 void CheckBoxPattern::HandleBlurEvent()
412 {
413     CHECK_NULL_VOID(paintMethod_);
414     RemoveIsFocusActiveUpdateEvent();
415     OnIsFocusActiveUpdate(false);
416 }
417 
AddIsFocusActiveUpdateEvent()418 void CheckBoxPattern::AddIsFocusActiveUpdateEvent()
419 {
420     if (!isFocusActiveUpdateEvent_) {
421         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
422             auto pattern = weak.Upgrade();
423             CHECK_NULL_VOID(pattern);
424             pattern->OnIsFocusActiveUpdate(isFocusAcitve);
425         };
426     }
427     auto host = GetHost();
428     CHECK_NULL_VOID(host);
429     auto pipline = host->GetContextRefPtr();
430     CHECK_NULL_VOID(pipline);
431     pipline->AddIsFocusActiveUpdateEvent(host, isFocusActiveUpdateEvent_);
432 }
433 
RemoveIsFocusActiveUpdateEvent()434 void CheckBoxPattern::RemoveIsFocusActiveUpdateEvent()
435 {
436     auto host = GetHost();
437     CHECK_NULL_VOID(host);
438     auto pipline = host->GetContextRefPtr();
439     CHECK_NULL_VOID(pipline);
440     pipline->RemoveIsFocusActiveUpdateEvent(host);
441 }
442 
OnIsFocusActiveUpdate(bool isFocusAcitve)443 void CheckBoxPattern::OnIsFocusActiveUpdate(bool isFocusAcitve)
444 {
445     CHECK_NULL_VOID(paintMethod_);
446     auto modifier = paintMethod_->GetCheckBoxModifier();
447     CHECK_NULL_VOID(modifier);
448     modifier->SetIsFocused(isFocusAcitve);
449 }
450 
OnClick()451 void CheckBoxPattern::OnClick()
452 {
453     if (UseContentModifier()) {
454         return;
455     }
456     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox onclick");
457     auto host = GetHost();
458     CHECK_NULL_VOID(host);
459     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
460     CHECK_NULL_VOID(paintProperty);
461     bool isSelected = false;
462     if (paintProperty->HasCheckBoxSelect()) {
463         isSelected = paintProperty->GetCheckBoxSelectValue();
464     } else {
465         isSelected = false;
466     }
467     paintProperty->UpdateCheckBoxSelect(!isSelected);
468     UpdateState();
469 }
470 
OnTouchDown()471 void CheckBoxPattern::OnTouchDown()
472 {
473     if (UseContentModifier()) {
474         return;
475     }
476     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox touch down %{public}d", isHover_);
477     if (isHover_) {
478         touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
479     } else {
480         touchHoverType_ = TouchHoverAnimationType::PRESS;
481     }
482     auto host = GetHost();
483     CHECK_NULL_VOID(host);
484     isTouch_ = true;
485     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
486 }
487 
OnTouchUp()488 void CheckBoxPattern::OnTouchUp()
489 {
490     if (UseContentModifier()) {
491         return;
492     }
493     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox touch up %{public}d", isHover_);
494     if (isHover_) {
495         touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
496     } else {
497         touchHoverType_ = TouchHoverAnimationType::NONE;
498     }
499     auto host = GetHost();
500     CHECK_NULL_VOID(host);
501     isTouch_ = false;
502     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
503 }
504 
UpdateUnSelect()505 void CheckBoxPattern::UpdateUnSelect()
506 {
507     auto host = GetHost();
508     CHECK_NULL_VOID(host);
509     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
510     CHECK_NULL_VOID(paintProperty);
511     if (paintProperty->HasCheckBoxSelect() && !paintProperty->GetCheckBoxSelectValue()) {
512         uiStatus_ = UIStatus::UNSELECTED;
513         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
514     }
515 }
516 
UpdateUIStatus(bool check)517 void CheckBoxPattern::UpdateUIStatus(bool check)
518 {
519     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox update status %{public}d", check);
520     uiStatus_ = check ? UIStatus::OFF_TO_ON : UIStatus::ON_TO_OFF;
521     auto host = GetHost();
522     CHECK_NULL_VOID(host);
523     if (UseContentModifier()) {
524         auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
525         CHECK_NULL_VOID(paintProperty);
526         paintProperty->UpdateCheckBoxSelect(check);
527         FireBuilder();
528     }
529     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
530 }
531 
UpdateGroupStatus(FrameNode * frameNode)532 void CheckBoxPattern::UpdateGroupStatus(FrameNode* frameNode)
533 {
534     CHECK_NULL_VOID(frameNode);
535     auto groupManager = GetGroupManager();
536     CHECK_NULL_VOID(groupManager);
537     auto eventHub = frameNode->GetOrCreateEventHub<CheckBoxEventHub>();
538     CHECK_NULL_VOID(eventHub);
539     auto group = eventHub->GetGroupName() + currentNavId_.value_or(groupManager->GetLastNavId());
540     groupManager->RemoveCheckBoxFromGroup(group, frameNode->GetId());
541     auto groupNode = groupManager->GetCheckboxGroup(group);
542     CHECK_NULL_VOID(groupNode);
543     auto checkboxList = groupManager->GetCheckboxList(group);
544     UpdateCheckBoxGroupStatus(groupNode, checkboxList);
545     auto pipeline = frameNode->GetContext();
546     CHECK_NULL_VOID(pipeline);
547     pipeline->RemoveVisibleAreaChangeNode(frameNode->GetId());
548 }
549 
550 
OnDetachFromFrameNode(FrameNode * frameNode)551 void CheckBoxPattern::OnDetachFromFrameNode(FrameNode* frameNode)
552 {
553     THREAD_SAFE_NODE_CHECK(frameNode, OnDetachFromFrameNode);
554     UpdateGroupStatus(frameNode);
555 }
556 
OnDetachFromMainTree()557 void CheckBoxPattern::OnDetachFromMainTree()
558 {
559     auto host = GetHost();
560     THREAD_SAFE_NODE_CHECK(host, OnDetachFromMainTree, host);
561 }
562 
CheckPageNode()563 void CheckBoxPattern::CheckPageNode()
564 {
565     if (Container::IsInSubContainer()) {
566         return;
567     }
568     auto host = GetHost();
569     CHECK_NULL_VOID(host);
570     auto prePageId = GetPrePageId();
571     auto pipelineContext = GetContext();
572     CHECK_NULL_VOID(pipelineContext);
573     auto stageManager = pipelineContext->GetStageManager();
574     CHECK_NULL_VOID(stageManager);
575     auto pageNode = stageManager->GetPageById(host->GetPageId());
576     CHECK_NULL_VOID(pageNode);
577     if (pageNode->GetId() != prePageId) {
578         auto pageEventHub = pageNode->GetOrCreateEventHub<NG::PageEventHub>();
579         CHECK_NULL_VOID(pageEventHub);
580         auto groupManager = pageEventHub->GetGroupManager();
581         CHECK_NULL_VOID(groupManager);
582         groupManager_ = groupManager;
583         auto group = GetGroupNameWithNavId();
584         groupManager->AddCheckBoxToGroup(group, host);
585         SetPrePageId(pageNode->GetId());
586     }
587 }
588 
UpdateState()589 void CheckBoxPattern::UpdateState()
590 {
591     auto host = GetHost();
592     CHECK_NULL_VOID(host);
593     auto pipelineContext = GetContext();
594     CHECK_NULL_VOID(pipelineContext);
595     auto groupManager = GetGroupManager();
596     CHECK_NULL_VOID(groupManager);
597     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
598     CHECK_NULL_VOID(paintProperty);
599     auto preGroup = GetPreGroup();
600     auto group = GetGroupNameWithNavId();
601     if (!preGroup.has_value()) {
602         groupManager->AddCheckBoxToGroup(group, host);
603         SetPrePageIdToLastPageId();
604         auto callback = [weak = WeakClaim(this)]() {
605             auto checkbox = weak.Upgrade();
606             if (checkbox) {
607                 checkbox->CheckPageNode();
608                 checkbox->CheckBoxGroupIsTrue();
609             }
610         };
611         pipelineContext->AddBuildFinishCallBack(callback);
612         if (paintProperty->HasCheckBoxSelect()) {
613             auto isSelected = paintProperty->GetCheckBoxSelectValue();
614             SetLastSelect(isSelected);
615         }
616         isFirstCreated_ = false;
617         SetPreGroup(group);
618         return;
619     }
620     if (preGroup.has_value() && preGroup.value() != group) {
621         groupManager->RemoveCheckBoxFromGroup(preGroup.value(), host->GetId());
622         groupManager->AddCheckBoxToGroup(group, host);
623         SetPrePageIdToLastPageId();
624     }
625     SetPreGroup(group);
626     ChangeSelfStatusAndNotify(paintProperty);
627     auto groupNode = groupManager->GetCheckboxGroup(group);
628     CHECK_NULL_VOID(groupNode);
629     auto checkboxList = groupManager->GetCheckboxList(group);
630     UpdateCheckBoxGroupStatus(groupNode, checkboxList);
631 }
632 
ChangeSelfStatusAndNotify(const RefPtr<CheckBoxPaintProperty> & paintProperty)633 void CheckBoxPattern::ChangeSelfStatusAndNotify(const RefPtr<CheckBoxPaintProperty>& paintProperty)
634 {
635     auto host = GetHost();
636     CHECK_NULL_VOID(host);
637     bool isSelected = false;
638     if (paintProperty->HasCheckBoxSelect()) {
639         isSelected = paintProperty->GetCheckBoxSelectValue();
640         if (lastSelect_ != isSelected) {
641             UpdateUIStatus(isSelected);
642             SetLastSelect(isSelected);
643             auto checkboxEventHub = GetOrCreateEventHub<CheckBoxEventHub>();
644             CHECK_NULL_VOID(checkboxEventHub);
645             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox node %{public}d update change event %{public}d",
646                 host->GetId(), isSelected);
647             checkboxEventHub->UpdateChangeEvent(isSelected);
648         }
649     }
650     StartCustomNodeAnimation(isSelected);
651     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
652     FireBuilder();
653 }
654 
StartEnterAnimation()655 void CheckBoxPattern::StartEnterAnimation()
656 {
657     auto host = GetHost();
658     CHECK_NULL_VOID(host);
659     AnimationOption option;
660     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
661     option.SetDuration(DEFAULT_CHECKBOX_ANIMATION_DURATION);
662     CHECK_NULL_VOID(builderNode_);
663     const auto& renderContext = builderNode_->GetRenderContext();
664     CHECK_NULL_VOID(renderContext);
665     renderContext->UpdateOpacity(0);
666     const auto& layoutProperty = builderNode_->GetLayoutProperty();
667     CHECK_NULL_VOID(layoutProperty);
668     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
669     const auto& eventHub = builderNode_->GetOrCreateEventHub<EventHub>();
670     if (eventHub) {
671         eventHub->SetEnabled(true);
672     }
673     AnimationUtils::Animate(
674         option,
675         [&]() {
676             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "check enter animation");
677             renderContext->UpdateOpacity(1);
678         },
679         nullptr, nullptr, host->GetContextRefPtr());
680 }
681 
StartExitAnimation()682 void CheckBoxPattern::StartExitAnimation()
683 {
684     auto host = GetHost();
685     CHECK_NULL_VOID(host);
686     AnimationOption option;
687     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
688     option.SetDuration(DEFAULT_CHECKBOX_ANIMATION_DURATION);
689     CHECK_NULL_VOID(builderNode_);
690     const auto& renderContext = builderNode_->GetRenderContext();
691     CHECK_NULL_VOID(renderContext);
692     AnimationUtils::Animate(
693         option,
694         [&]() {
695             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "check exit animation");
696             renderContext->UpdateOpacity(0);
697         },
698         nullptr, nullptr, host->GetContextRefPtr());
699     const auto& eventHub = builderNode_->GetOrCreateEventHub<EventHub>();
700     if (eventHub) {
701         eventHub->SetEnabled(false);
702     }
703 }
704 
LoadBuilder()705 void CheckBoxPattern::LoadBuilder()
706 {
707     RefPtr<UINode> customNode;
708     if (builder_.has_value()) {
709         auto host = GetHost();
710         CHECK_NULL_VOID(host);
711         if (builderNode_) {
712             host->RemoveChildAndReturnIndex(builderNode_);
713         }
714         NG::ScopedViewStackProcessor builderViewStackProcessor;
715         builder_.value()();
716         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
717         CHECK_NULL_VOID(customNode);
718         builderNode_ = AceType::DynamicCast<FrameNode>(customNode);
719         CHECK_NULL_VOID(builderNode_);
720         builderNode_->MountToParent(host);
721         host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
722     }
723 }
724 
StartCustomNodeAnimation(bool select)725 void CheckBoxPattern::StartCustomNodeAnimation(bool select)
726 {
727     if (!isFirstCreated_ && builder_.has_value()) {
728         if (select) {
729             StartEnterAnimation();
730         } else {
731             StartExitAnimation();
732         }
733     }
734 }
735 
UpdateCheckBoxGroupStatus(RefPtr<FrameNode> checkBoxGroupNode,const std::list<RefPtr<FrameNode>> & list)736 void CheckBoxPattern::UpdateCheckBoxGroupStatus(
737     RefPtr<FrameNode> checkBoxGroupNode, const std::list<RefPtr<FrameNode>>& list)
738 {
739     std::vector<std::string> vec;
740     bool haveCheckBoxSelected = false;
741     bool isAllCheckBoxSelected = true;
742     for (auto node : list) {
743         if (!node) {
744             continue;
745         }
746         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
747         CHECK_NULL_VOID(paintProperty);
748         if (paintProperty->GetCheckBoxSelectValue(false)) {
749             auto eventHub = node->GetOrCreateEventHub<CheckBoxEventHub>();
750             CHECK_NULL_VOID(eventHub);
751             vec.push_back(eventHub->GetName());
752             haveCheckBoxSelected = true;
753         } else {
754             isAllCheckBoxSelected = false;
755         }
756     }
757     ChangeGroupStatusAndNotify(checkBoxGroupNode, vec, haveCheckBoxSelected, isAllCheckBoxSelected);
758 }
759 
ChangeGroupStatusAndNotify(const RefPtr<FrameNode> & checkBoxGroupNode,const std::vector<std::string> & vec,bool haveCheckBoxSelected,bool isAllCheckBoxSelected)760 void CheckBoxPattern::ChangeGroupStatusAndNotify(const RefPtr<FrameNode>& checkBoxGroupNode,
761     const std::vector<std::string>& vec, bool haveCheckBoxSelected, bool isAllCheckBoxSelected)
762 {
763     CHECK_NULL_VOID(checkBoxGroupNode);
764     auto groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
765     CHECK_NULL_VOID(groupPaintProperty);
766     auto pattern = checkBoxGroupNode->GetPattern<CheckBoxGroupPattern>();
767     CHECK_NULL_VOID(pattern);
768     auto preStatus = groupPaintProperty->GetSelectStatus();
769     if (haveCheckBoxSelected) {
770         if (isAllCheckBoxSelected) {
771             groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
772             pattern->UpdateUIStatus(true);
773         } else {
774             groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::PART);
775             pattern->ResetUIStatus();
776         }
777     } else {
778         groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
779         pattern->UpdateUIStatus(false);
780     }
781     checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
782     auto status = groupPaintProperty->GetSelectStatus();
783     if (preStatus != status && (preStatus == CheckBoxGroupPaintProperty::SelectStatus::ALL ||
784                                    status == CheckBoxGroupPaintProperty::SelectStatus::ALL)) {
785         pattern->SetSkipFlag(true);
786     }
787     CheckboxGroupResult groupResult(vec, int(status));
788     auto eventHub = checkBoxGroupNode->GetOrCreateEventHub<CheckBoxGroupEventHub>();
789     CHECK_NULL_VOID(eventHub);
790     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "update checkboxgroup result %d", groupResult.GetStatus());
791     eventHub->UpdateChangeEvent(&groupResult);
792 }
793 
CheckBoxGroupIsTrue()794 void CheckBoxPattern::CheckBoxGroupIsTrue()
795 {
796     auto host = GetHost();
797     CHECK_NULL_VOID(host);
798     auto groupManager = GetGroupManager();
799     CHECK_NULL_VOID(groupManager);
800     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
801     CHECK_NULL_VOID(paintProperty);
802     auto group = GetGroupNameWithNavId();
803     RefPtr<FrameNode> checkBoxGroupNode = groupManager->GetCheckboxGroup(group);
804     CHECK_NULL_VOID(checkBoxGroupNode);
805     std::vector<std::string> vec;
806     bool allSelectIsNull = true;
807     const auto& list = groupManager->GetCheckboxList(group);
808     for (auto node : list) {
809         if (!node) {
810             continue;
811         }
812         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
813         CHECK_NULL_VOID(paintProperty);
814         if (paintProperty->HasCheckBoxSelect()) {
815             allSelectIsNull = false;
816         } else {
817             paintProperty->UpdateCheckBoxSelect(false);
818         }
819     }
820     const auto& groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
821     CHECK_NULL_VOID(groupPaintProperty);
822     if (!groupManager->GetCheckboxGroupIsChange(group) && groupPaintProperty->GetIsCheckBoxCallbackDealed()) {
823         return;
824     }
825     // All checkboxes do not set select status.
826     if (allSelectIsNull && groupPaintProperty->GetCheckBoxGroupSelectValue(false)) {
827         InitCheckBoxStatusByGroup(checkBoxGroupNode, groupPaintProperty, list);
828     }
829     // Some checkboxes set select status.
830     if (!allSelectIsNull) {
831         UpdateCheckBoxGroupStatus(checkBoxGroupNode, list);
832     }
833     groupPaintProperty->SetIsCheckBoxCallbackDealed(true);
834     groupManager->SetCheckboxGroupIsChange(group, false);
835 }
836 
InitCheckBoxStatusByGroup(RefPtr<FrameNode> checkBoxGroupNode,const RefPtr<CheckBoxGroupPaintProperty> & groupPaintProperty,const std::list<RefPtr<FrameNode>> & list)837 void CheckBoxPattern::InitCheckBoxStatusByGroup(RefPtr<FrameNode> checkBoxGroupNode,
838     const RefPtr<CheckBoxGroupPaintProperty>& groupPaintProperty, const std::list<RefPtr<FrameNode>>& list)
839 {
840     if (groupPaintProperty->GetCheckBoxGroupSelectValue(false)) {
841         groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
842         groupPaintProperty->UpdateCheckBoxGroupSelect(true);
843         checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
844         for (auto node : list) {
845             if (!node) {
846                 continue;
847             }
848             auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
849             CHECK_NULL_VOID(paintProperty);
850             paintProperty->UpdateCheckBoxSelect(true);
851             auto checkBoxPattern = node->GetPattern<CheckBoxPattern>();
852             CHECK_NULL_VOID(checkBoxPattern);
853             checkBoxPattern->StartCustomNodeAnimation(true);
854             checkBoxPattern->UpdateUIStatus(true);
855             checkBoxPattern->SetLastSelect(true);
856         }
857     }
858 }
859 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)860 void CheckBoxPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
861 {
862     CHECK_NULL_VOID(focusHub);
863     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
864         auto pattern = wp.Upgrade();
865         if (pattern) {
866             pattern->GetInnerFocusPaintRect(paintRect);
867         }
868     };
869     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
870 
871     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
872         auto pattern = wp.Upgrade();
873         if (pattern) {
874             return pattern->OnKeyEvent(event);
875         }
876         return false;
877     };
878     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
879 }
880 
OnKeyEvent(const KeyEvent & event)881 bool CheckBoxPattern::OnKeyEvent(const KeyEvent& event)
882 {
883     if (event.action == KeyAction::DOWN && event.code == KeyCode::KEY_FUNCTION) {
884         OnClick();
885         return true;
886     }
887     return false;
888 }
889 
IsSquareStyleBox()890 bool CheckBoxPattern::IsSquareStyleBox()
891 {
892     auto host = GetHost();
893     CHECK_NULL_RETURN(host, false);
894     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
895     CHECK_NULL_RETURN(paintProperty, false);
896     CheckBoxStyle checkboxStyle = CheckBoxStyle::CIRCULAR_STYLE;
897     if (paintProperty->HasCheckBoxSelectedStyle()) {
898         checkboxStyle = paintProperty->GetCheckBoxSelectedStyleValue(CheckBoxStyle::CIRCULAR_STYLE);
899     } else {
900         checkboxStyle = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) ?
901             CheckBoxStyle::CIRCULAR_STYLE : CheckBoxStyle::SQUARE_STYLE;
902     }
903     return checkboxStyle == CheckBoxStyle::SQUARE_STYLE;
904 }
905 
GetInnerFocusPaintRect(RoundRect & paintRect)906 void CheckBoxPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
907 {
908     auto host = GetHost();
909     CHECK_NULL_VOID(host);
910     auto* pipelineContext = host->GetContextWithCheck();
911     CHECK_NULL_VOID(pipelineContext);
912     auto checkBoxTheme = pipelineContext->GetTheme<CheckboxTheme>(GetThemeScopeId());
913     CHECK_NULL_VOID(checkBoxTheme);
914     auto borderRadius = checkBoxTheme->GetFocusRadius().ConvertToPx();
915     auto focusPaintPadding = checkBoxTheme->GetFocusPaintPadding().ConvertToPx();
916     auto isSquare = IsSquareStyleBox();
917     auto squareFocusBoardSize = checkBoxTheme->GetFocusBoardSize();
918     auto roundFocusBoardSize = checkBoxTheme->GetRoundFocusBoardSize();
919     if ((squareFocusBoardSize > roundFocusBoardSize) && isSquare) {
920         focusPaintPadding += (squareFocusBoardSize.ConvertToPx() - roundFocusBoardSize.ConvertToPx());
921     }
922     float originX = offset_.GetX() - focusPaintPadding;
923     float originY = offset_.GetY() - focusPaintPadding;
924     float width = size_.Width() + 2 * focusPaintPadding;
925     float height = size_.Height() + 2 * focusPaintPadding;
926     paintRect.SetRect({ originX, originY, width, height });
927     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, borderRadius, borderRadius);
928     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, borderRadius, borderRadius);
929     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, borderRadius, borderRadius);
930     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, borderRadius, borderRadius);
931 }
932 
GetFocusPattern() const933 FocusPattern CheckBoxPattern::GetFocusPattern() const
934 {
935     auto host = GetHost();
936     CHECK_NULL_RETURN(host, FocusPattern());
937     auto* pipeline = host->GetContextWithCheck();
938     CHECK_NULL_RETURN(pipeline, FocusPattern());
939     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>(GetThemeScopeId());
940     CHECK_NULL_RETURN(checkBoxTheme, FocusPattern());
941     auto activeColor = checkBoxTheme->GetFocusLineColor();
942     FocusPaintParam focusPaintParam;
943     focusPaintParam.SetPaintColor(activeColor);
944     return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
945 }
946 
947 // Set the default hot zone for the component.
AddHotZoneRect()948 void CheckBoxPattern::AddHotZoneRect()
949 {
950     hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
951     hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
952     hotZoneSize_.SetWidth(size_.Width() + 2 * hotZoneHorizontalPadding_.ConvertToPx());
953     hotZoneSize_.SetHeight(size_.Height() + 2 * hotZoneVerticalPadding_.ConvertToPx());
954     DimensionRect hotZoneRegion;
955     hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
956     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
957     auto host = GetHost();
958     CHECK_NULL_VOID(host);
959     auto gestureHub = host->GetOrCreateGestureEventHub();
960     CHECK_NULL_VOID(gestureHub);
961     std::vector<DimensionRect> hotZoneRegions;
962     hotZoneRegions.emplace_back(hotZoneRegion);
963     gestureHub->SetResponseRegion(hotZoneRegions);
964 }
965 
RemoveLastHotZoneRect() const966 void CheckBoxPattern::RemoveLastHotZoneRect() const
967 {
968     auto host = GetHost();
969     CHECK_NULL_VOID(host);
970     host->RemoveLastHotZoneRect();
971 }
972 
ProvideRestoreInfo()973 std::string CheckBoxPattern::ProvideRestoreInfo()
974 {
975     auto jsonObj = JsonUtil::Create(true);
976     auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
977     CHECK_NULL_RETURN(checkBoxPaintProperty, "");
978     jsonObj->Put("isOn", checkBoxPaintProperty->GetCheckBoxSelect().value_or(false));
979     return jsonObj->ToString();
980 }
981 
OnRestoreInfo(const std::string & restoreInfo)982 void CheckBoxPattern::OnRestoreInfo(const std::string& restoreInfo)
983 {
984     auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
985     CHECK_NULL_VOID(checkBoxPaintProperty);
986     auto info = JsonUtil::ParseJsonString(restoreInfo);
987     if (!info->IsValid() || !info->IsObject()) {
988         return;
989     }
990     auto jsonCheckBoxSelect = info->GetValue("isOn");
991     checkBoxPaintProperty->UpdateCheckBoxSelect(jsonCheckBoxSelect->GetBool());
992 }
993 
SetCheckBoxSelect(bool select)994 void CheckBoxPattern::SetCheckBoxSelect(bool select)
995 {
996     auto host = GetHost();
997     CHECK_NULL_VOID(host);
998     auto eventHub = host->GetOrCreateEventHub<EventHub>();
999     CHECK_NULL_VOID(eventHub);
1000     auto enabled = eventHub->IsEnabled();
1001     if (!enabled) {
1002         return;
1003     }
1004     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
1005     CHECK_NULL_VOID(paintProperty);
1006     paintProperty->UpdateCheckBoxSelect(select);
1007     UpdateState();
1008     OnModifyDone();
1009 }
1010 
FireBuilder()1011 void CheckBoxPattern::FireBuilder()
1012 {
1013     auto host = GetHost();
1014     CHECK_NULL_VOID(host);
1015     if (!makeFunc_.has_value() && !toggleMakeFunc_.has_value()) {
1016         host->RemoveChildAndReturnIndex(contentModifierNode_);
1017         contentModifierNode_ = nullptr;
1018         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1019         return;
1020     }
1021     auto node = BuildContentModifierNode();
1022     if (contentModifierNode_ == node) {
1023         return;
1024     }
1025     auto renderContext = host->GetRenderContext();
1026     CHECK_NULL_VOID(renderContext);
1027     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
1028     host->RemoveChildAndReturnIndex(contentModifierNode_);
1029     contentModifierNode_ = node;
1030     CHECK_NULL_VOID(contentModifierNode_);
1031     host->AddChild(contentModifierNode_, 0);
1032     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1033 }
1034 
BuildContentModifierNode()1035 RefPtr<FrameNode> CheckBoxPattern::BuildContentModifierNode()
1036 {
1037     auto host = GetHost();
1038     CHECK_NULL_RETURN(host, nullptr);
1039     auto eventHub = host->GetOrCreateEventHub<CheckBoxEventHub>();
1040     CHECK_NULL_RETURN(eventHub, nullptr);
1041     auto name = eventHub->GetName();
1042     auto enabled = eventHub->IsEnabled();
1043     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
1044     CHECK_NULL_RETURN(paintProperty, nullptr);
1045     bool isSelected = false;
1046     if (paintProperty->HasCheckBoxSelect()) {
1047         isSelected = paintProperty->GetCheckBoxSelectValue();
1048     } else {
1049         isSelected = false;
1050     }
1051     if (host->GetHostTag() == V2::CHECKBOX_ETS_TAG && toggleMakeFunc_.has_value()) {
1052         return (toggleMakeFunc_.value())(ToggleConfiguration(enabled, isSelected));
1053     }
1054     CheckBoxConfiguration checkBoxConfiguration(name, isSelected, enabled);
1055     return (makeFunc_.value())(checkBoxConfiguration);
1056 }
1057 
UpdatePaintPropertyBySettingData(RefPtr<CheckBoxPaintProperty> paintProp)1058 void CheckBoxPattern::UpdatePaintPropertyBySettingData(RefPtr<CheckBoxPaintProperty> paintProp)
1059 {
1060     if (checkboxSettingData_.selectedColor.has_value()) {
1061         paintProp->UpdateCheckBoxSelectedColor(checkboxSettingData_.selectedColor.value());
1062     }
1063     if (checkboxSettingData_.unselectedColor.has_value()) {
1064         paintProp->UpdateCheckBoxUnSelectedColor(checkboxSettingData_.unselectedColor.value());
1065     }
1066     if (checkboxSettingData_.strokeColor.has_value()) {
1067         paintProp->UpdateCheckBoxCheckMarkColor(checkboxSettingData_.strokeColor.value());
1068     }
1069 }
1070 
OnColorConfigurationUpdate()1071 void CheckBoxPattern::OnColorConfigurationUpdate()
1072 {
1073     auto host = GetHost();
1074     CHECK_NULL_VOID(host);
1075     auto checkBoxPaintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
1076     CHECK_NULL_VOID(checkBoxPaintProperty);
1077     OnThemeScopeUpdate(host->GetThemeScopeId());
1078     UpdatePaintPropertyBySettingData(checkBoxPaintProperty);
1079     host->MarkModifyDone();
1080     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1081 }
1082 
OnThemeScopeUpdate(int32_t themeScopeId)1083 bool CheckBoxPattern::OnThemeScopeUpdate(int32_t themeScopeId)
1084 {
1085     auto host = GetHost();
1086     CHECK_NULL_RETURN(host, false);
1087     auto* pipeline = host->GetContext();
1088     CHECK_NULL_RETURN(pipeline, false);
1089     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>(themeScopeId);
1090     CHECK_NULL_RETURN(checkBoxTheme, false);
1091     auto result = false;
1092     auto checkBoxPaintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
1093     CHECK_NULL_RETURN(checkBoxPaintProperty, false);
1094     if (!checkBoxPaintProperty->GetCheckBoxSelectedColorFlagByUserValue(false)) {
1095         checkBoxPaintProperty->UpdateCheckBoxSelectedColor(checkBoxTheme->GetActiveColor());
1096         result = true;
1097     }
1098     if (!checkBoxPaintProperty->GetCheckBoxUnSelectedColorFlagByUserValue(false)) {
1099         checkBoxPaintProperty->UpdateCheckBoxUnSelectedColor(checkBoxTheme->GetInactiveColor());
1100         result = true;
1101     }
1102 
1103     if (!checkBoxPaintProperty->GetCheckBoxCheckMarkColorFlagByUserValue(false)) {
1104         checkBoxPaintProperty->UpdateCheckBoxCheckMarkColor(checkBoxTheme->GetPointColor());
1105         result = true;
1106     }
1107     return result;
1108 }
1109 
DumpInfo()1110 void CheckBoxPattern::DumpInfo()
1111 {
1112     auto eventHub = GetOrCreateEventHub<CheckBoxEventHub>();
1113     CHECK_NULL_VOID(eventHub);
1114     DumpLog::GetInstance().AddDesc("Name: " + eventHub->GetName());
1115     DumpLog::GetInstance().AddDesc("GroupName: " + eventHub->GetGroupName());
1116 
1117     auto paintProperty = GetPaintProperty<CheckBoxPaintProperty>();
1118     CHECK_NULL_VOID(paintProperty);
1119     if (paintProperty->HasCheckBoxSelectedStyle()) {
1120         DumpLog::GetInstance().AddDesc(
1121             "Shape: " + CheckBoxModel::ToString(paintProperty->GetCheckBoxSelectedStyleValue()));
1122     }
1123     if (paintProperty->HasCheckBoxSelect()) {
1124         DumpLog::GetInstance().AddDesc(
1125             "IsSelected: " + std::string(paintProperty->GetCheckBoxSelectValue() ? "true" : "false"));
1126     }
1127     if (paintProperty->HasCheckBoxSelectedColor()) {
1128         DumpLog::GetInstance().AddDesc("SelectedColor: " + paintProperty->GetCheckBoxSelectedColorValue().ToString());
1129     }
1130     if (paintProperty->HasCheckBoxUnSelectedColor()) {
1131         DumpLog::GetInstance().AddDesc(
1132             "UnSelectedColor: " + paintProperty->GetCheckBoxUnSelectedColorValue().ToString());
1133     }
1134     if (paintProperty->HasCheckBoxCheckMarkSize()) {
1135         DumpLog::GetInstance().AddDesc("MarkSize: " + paintProperty->GetCheckBoxCheckMarkSizeValue().ToString());
1136     }
1137     if (paintProperty->HasCheckBoxCheckMarkWidth()) {
1138         DumpLog::GetInstance().AddDesc("MarkWidth: " + paintProperty->GetCheckBoxCheckMarkWidthValue().ToString());
1139     }
1140     if (paintProperty->HasCheckBoxCheckMarkColor()) {
1141         DumpLog::GetInstance().AddDesc("MarkColor: " + paintProperty->GetCheckBoxCheckMarkColorValue().ToString());
1142     }
1143 }
1144 
SetPrePageIdToLastPageId()1145 void CheckBoxPattern::SetPrePageIdToLastPageId()
1146 {
1147     if (!Container::IsInSubContainer()) {
1148         auto pipelineContext = PipelineContext::GetCurrentContext();
1149         CHECK_NULL_VOID(pipelineContext);
1150         auto stageManager = pipelineContext->GetStageManager();
1151         CHECK_NULL_VOID(stageManager);
1152         auto pageNode = stageManager->GetLastPage();
1153         CHECK_NULL_VOID(pageNode);
1154         SetPrePageId(pageNode->GetId());
1155     }
1156 }
1157 
UpdateNavIdAndState(const RefPtr<FrameNode> & host)1158 void CheckBoxPattern::UpdateNavIdAndState(const RefPtr<FrameNode>& host)
1159 {
1160     auto groupManager = GetGroupManager();
1161     CHECK_NULL_VOID(groupManager);
1162     auto parent = host->GetParent();
1163     while (parent) {
1164         if (parent->GetTag() == V2::NAVDESTINATION_CONTENT_ETS_TAG) {
1165             currentNavId_ = std::to_string(parent->GetId());
1166             groupManager->SetLastNavId(currentNavId_);
1167             UpdateState();
1168             return;
1169         }
1170         parent = parent->GetParent();
1171     }
1172     if (!currentNavId_.value_or("").empty()) {
1173         currentNavId_ = "";
1174         groupManager->SetLastNavId(std::nullopt);
1175         UpdateState();
1176     }
1177 }
1178 
OnAttachToMainTree()1179 void CheckBoxPattern::OnAttachToMainTree()
1180 {
1181     auto host = GetHost();
1182     CHECK_NULL_VOID(host);
1183     THREAD_SAFE_NODE_CHECK(host, OnAttachToMainTree, host);
1184     UpdateNavIdAndState(host);
1185 }
1186 
GetGroupNameWithNavId()1187 std::string CheckBoxPattern::GetGroupNameWithNavId()
1188 {
1189     auto host = GetHost();
1190     CHECK_NULL_RETURN(host, "");
1191     auto eventHub = host->GetOrCreateEventHub<CheckBoxEventHub>();
1192     CHECK_NULL_RETURN(eventHub, "");
1193     if (currentNavId_.has_value()) {
1194         return eventHub->GetGroupName() + currentNavId_.value();
1195     }
1196     auto groupManager = GetGroupManager();
1197     CHECK_NULL_RETURN(groupManager, eventHub->GetGroupName());
1198     return eventHub->GetGroupName() + groupManager->GetLastNavId();
1199 }
1200 
GetGroupManager()1201 RefPtr<GroupManager> CheckBoxPattern::GetGroupManager()
1202 {
1203     auto manager = groupManager_.Upgrade();
1204     if (manager) {
1205         return manager;
1206     }
1207     groupManager_ = GroupManager::GetGroupManager();
1208     return groupManager_.Upgrade();
1209 }
1210 
RegisterVisibleAreaChange()1211 void CheckBoxPattern::RegisterVisibleAreaChange()
1212 {
1213     if (hasVisibleChangeRegistered_) {
1214         return;
1215     }
1216     auto host = GetHost();
1217     CHECK_NULL_VOID(host);
1218     auto pipeline = host->GetContext();
1219     CHECK_NULL_VOID(pipeline);
1220     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
1221         auto pattern = weak.Upgrade();
1222         CHECK_NULL_VOID(pattern);
1223         pattern->SetNeedAnimation(visible);
1224     };
1225     std::vector<double> ratioList = {0.0};
1226     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, true);
1227     hasVisibleChangeRegistered_ = true;
1228 }
1229 
SetNeedAnimation(bool visible)1230 void CheckBoxPattern::SetNeedAnimation(bool visible)
1231 {
1232     visible_ = visible;
1233     CHECK_NULL_VOID(paintMethod_);
1234     paintMethod_->SetNeedAnimation(visible);
1235 }
1236 } // namespace OHOS::Ace::NG
1237