• 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/checkbox/checkbox_pattern.h"
17 
18 #include "core/common/recorder/node_data_cache.h"
19 #include "core/components/checkable/checkable_component.h"
20 #include "core/components/checkable/checkable_theme.h"
21 #include "core/components_ng/pattern/checkbox/checkbox_layout_algorithm.h"
22 #include "core/components_ng/pattern/checkbox/checkbox_paint_property.h"
23 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_paint_property.h"
24 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_pattern.h"
25 #include "core/components_ng/pattern/stage/page_event_hub.h"
26 #include "core/components_ng/property/calc_length.h"
27 #include "core/components_ng/property/property.h"
28 #include "core/components_v2/inspector/inspector_constants.h"
29 #include "core/event/touch_event.h"
30 #include "core/pipeline/base/constants.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32 
33 namespace OHOS::Ace::NG {
34 namespace {
35 const Color ITEM_FILL_COLOR = Color::TRANSPARENT;
36 constexpr int32_t DEFAULT_CHECKBOX_ANIMATION_DURATION = 100;
37 } // namespace
38 
OnAttachToFrameNode()39 void CheckBoxPattern::OnAttachToFrameNode()
40 {
41     auto host = GetHost();
42     CHECK_NULL_VOID(host);
43     host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
44 }
45 
SetBuilderNodeHidden()46 void CheckBoxPattern::SetBuilderNodeHidden()
47 {
48     CHECK_NULL_VOID(builderNode_);
49     auto layoutProperty = builderNode_->GetLayoutProperty();
50     CHECK_NULL_VOID(layoutProperty);
51     layoutProperty->UpdateVisibility(VisibleType::GONE);
52 }
53 
UpdateIndicator()54 void CheckBoxPattern::UpdateIndicator()
55 {
56     auto host = GetHost();
57     CHECK_NULL_VOID(host);
58     if (builder_.has_value() && !UseContentModifier()) {
59         LoadBuilder();
60         auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
61         CHECK_NULL_VOID(paintProperty);
62         bool isSelected = false;
63         if (paintProperty->HasCheckBoxSelect()) {
64             isSelected = paintProperty->GetCheckBoxSelectValue();
65             if (!isSelected) {
66                 SetBuilderNodeHidden();
67             }
68         } else {
69             paintProperty->UpdateCheckBoxSelect(false);
70             SetBuilderNodeHidden();
71         }
72     } else if (builderNode_) {
73         host->RemoveChildAndReturnIndex(builderNode_);
74         builderNode_ = nullptr;
75     }
76 }
77 
OnModifyDone()78 void CheckBoxPattern::OnModifyDone()
79 {
80     Pattern::OnModifyDone();
81     FireBuilder();
82     UpdateIndicator();
83     UpdateState();
84     auto host = GetHost();
85     CHECK_NULL_VOID(host);
86     auto pipeline = GetContext();
87     CHECK_NULL_VOID(pipeline);
88     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
89     CHECK_NULL_VOID(checkBoxTheme);
90     auto layoutProperty = host->GetLayoutProperty();
91     CHECK_NULL_VOID(layoutProperty);
92     MarginProperty margin;
93     margin.left = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
94     margin.right = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
95     margin.top = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
96     margin.bottom = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
97     auto& setMargin = layoutProperty->GetMarginProperty();
98     if (setMargin) {
99         if (setMargin->left.has_value()) {
100             margin.left = setMargin->left;
101         }
102         if (setMargin->right.has_value()) {
103             margin.right = setMargin->right;
104         }
105         if (setMargin->top.has_value()) {
106             margin.top = setMargin->top;
107         }
108         if (setMargin->bottom.has_value()) {
109             margin.bottom = setMargin->bottom;
110         }
111     }
112     layoutProperty->UpdateMargin(margin);
113     hotZoneHorizontalPadding_ = checkBoxTheme->GetHotZoneHorizontalPadding();
114     hotZoneVerticalPadding_ = checkBoxTheme->GetHotZoneVerticalPadding();
115     InitClickEvent();
116     InitTouchEvent();
117     InitMouseEvent();
118     auto focusHub = host->GetFocusHub();
119     CHECK_NULL_VOID(focusHub);
120     InitOnKeyEvent(focusHub);
121     SetAccessibilityAction();
122 }
123 
SetAccessibilityAction()124 void CheckBoxPattern::SetAccessibilityAction()
125 {
126     auto host = GetHost();
127     CHECK_NULL_VOID(host);
128     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
129     CHECK_NULL_VOID(accessibilityProperty);
130     accessibilityProperty->SetActionSelect([weakPtr = WeakClaim(this)]() {
131         const auto& pattern = weakPtr.Upgrade();
132         CHECK_NULL_VOID(pattern);
133         pattern->UpdateSelectStatus(true);
134     });
135 
136     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
137         const auto& pattern = weakPtr.Upgrade();
138         CHECK_NULL_VOID(pattern);
139         pattern->UpdateSelectStatus(false);
140     });
141 }
142 
UpdateSelectStatus(bool isSelected)143 void CheckBoxPattern::UpdateSelectStatus(bool isSelected)
144 {
145     auto host = GetHost();
146     CHECK_NULL_VOID(host);
147     auto context = host->GetRenderContext();
148     CHECK_NULL_VOID(context);
149     MarkIsSelected(isSelected);
150     context->OnMouseSelectUpdate(isSelected, ITEM_FILL_COLOR, ITEM_FILL_COLOR);
151 }
152 
MarkIsSelected(bool isSelected)153 void CheckBoxPattern::MarkIsSelected(bool isSelected)
154 {
155     if (lastSelect_ == isSelected) {
156         return;
157     }
158     lastSelect_ = isSelected;
159     auto eventHub = GetEventHub<CheckBoxEventHub>();
160     CHECK_NULL_VOID(eventHub);
161     eventHub->UpdateChangeEvent(isSelected);
162     auto host = GetHost();
163     CHECK_NULL_VOID(host);
164     if (isSelected) {
165         eventHub->UpdateCurrentUIState(UI_STATE_SELECTED);
166         host->OnAccessibilityEvent(AccessibilityEventType::SELECTED);
167     } else {
168         eventHub->ResetCurrentUIState(UI_STATE_SELECTED);
169         host->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
170     }
171 }
172 
OnAfterModifyDone()173 void CheckBoxPattern::OnAfterModifyDone()
174 {
175     auto host = GetHost();
176     CHECK_NULL_VOID(host);
177     auto inspectorId = host->GetInspectorId().value_or("");
178     if (inspectorId.empty()) {
179         return;
180     }
181     auto eventHub = host->GetEventHub<CheckBoxEventHub>();
182     CHECK_NULL_VOID(eventHub);
183     Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, eventHub->GetName(), lastSelect_);
184 }
185 
InitClickEvent()186 void CheckBoxPattern::InitClickEvent()
187 {
188     if (clickListener_) {
189         return;
190     }
191     auto host = GetHost();
192     CHECK_NULL_VOID(host);
193     auto gesture = host->GetOrCreateGestureEventHub();
194     CHECK_NULL_VOID(gesture);
195     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
196         auto checkboxPattern = weak.Upgrade();
197         CHECK_NULL_VOID(checkboxPattern);
198         checkboxPattern->OnClick();
199     };
200     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
201     gesture->AddClickEvent(clickListener_);
202 }
203 
InitTouchEvent()204 void CheckBoxPattern::InitTouchEvent()
205 {
206     if (touchListener_) {
207         return;
208     }
209     auto host = GetHost();
210     CHECK_NULL_VOID(host);
211     auto gesture = host->GetOrCreateGestureEventHub();
212     CHECK_NULL_VOID(gesture);
213     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
214         auto checkboxPattern = weak.Upgrade();
215         CHECK_NULL_VOID(checkboxPattern);
216         if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
217             checkboxPattern->OnTouchDown();
218         }
219         if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
220             info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
221             checkboxPattern->OnTouchUp();
222         }
223     };
224     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
225     gesture->AddTouchEvent(touchListener_);
226 }
227 
InitMouseEvent()228 void CheckBoxPattern::InitMouseEvent()
229 {
230     if (mouseEvent_) {
231         return;
232     }
233     auto host = GetHost();
234     CHECK_NULL_VOID(host);
235     auto gesture = host->GetOrCreateGestureEventHub();
236     CHECK_NULL_VOID(gesture);
237     auto eventHub = host->GetEventHub<CheckBoxEventHub>();
238     auto inputHub = eventHub->GetOrCreateInputEventHub();
239 
240     auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
241         auto pattern = weak.Upgrade();
242         if (pattern) {
243             pattern->HandleMouseEvent(isHover);
244         }
245     };
246     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
247     inputHub->AddOnHoverEvent(mouseEvent_);
248 }
249 
HandleMouseEvent(bool isHover)250 void CheckBoxPattern::HandleMouseEvent(bool isHover)
251 {
252     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox on hover %{public}d", isHover);
253     isHover_ = isHover;
254     if (isHover) {
255         touchHoverType_ = TouchHoverAnimationType::HOVER;
256     } else {
257         touchHoverType_ = TouchHoverAnimationType::NONE;
258     }
259     auto host = GetHost();
260     CHECK_NULL_VOID(host);
261     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
262 }
263 
OnClick()264 void CheckBoxPattern::OnClick()
265 {
266     if (UseContentModifier()) {
267         return;
268     }
269     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox onclick");
270     auto host = GetHost();
271     CHECK_NULL_VOID(host);
272     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
273     CHECK_NULL_VOID(paintProperty);
274     bool isSelected = false;
275     if (paintProperty->HasCheckBoxSelect()) {
276         isSelected = paintProperty->GetCheckBoxSelectValue();
277     } else {
278         isSelected = false;
279     }
280     paintProperty->UpdateCheckBoxSelect(!isSelected);
281     UpdateState();
282 }
283 
OnTouchDown()284 void CheckBoxPattern::OnTouchDown()
285 {
286     if (UseContentModifier()) {
287         return;
288     }
289     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox touch down %{public}d", isHover_);
290     if (isHover_) {
291         touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
292     } else {
293         touchHoverType_ = TouchHoverAnimationType::PRESS;
294     }
295     auto host = GetHost();
296     CHECK_NULL_VOID(host);
297     isTouch_ = true;
298     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
299 }
300 
OnTouchUp()301 void CheckBoxPattern::OnTouchUp()
302 {
303     if (UseContentModifier()) {
304         return;
305     }
306     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox touch up %{public}d", isHover_);
307     if (isHover_) {
308         touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
309     } else {
310         touchHoverType_ = TouchHoverAnimationType::NONE;
311     }
312     auto host = GetHost();
313     CHECK_NULL_VOID(host);
314     isTouch_ = false;
315     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
316 }
317 
UpdateUnSelect()318 void CheckBoxPattern::UpdateUnSelect()
319 {
320     auto host = GetHost();
321     CHECK_NULL_VOID(host);
322     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
323     CHECK_NULL_VOID(paintProperty);
324     if (paintProperty->HasCheckBoxSelect() && !paintProperty->GetCheckBoxSelectValue()) {
325         uiStatus_ = UIStatus::UNSELECTED;
326         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
327     }
328 }
329 
UpdateUIStatus(bool check)330 void CheckBoxPattern::UpdateUIStatus(bool check)
331 {
332     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox update status %{public}d", check);
333     uiStatus_ = check ? UIStatus::OFF_TO_ON : UIStatus::ON_TO_OFF;
334     auto host = GetHost();
335     CHECK_NULL_VOID(host);
336     if (UseContentModifier()) {
337         auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
338         CHECK_NULL_VOID(paintProperty);
339         paintProperty->UpdateCheckBoxSelect(check);
340         FireBuilder();
341     }
342     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
343 }
344 
OnDetachFromFrameNode(FrameNode * frameNode)345 void CheckBoxPattern::OnDetachFromFrameNode(FrameNode* frameNode)
346 {
347     CHECK_NULL_VOID(frameNode);
348     auto groupManager = GetGroupManager();
349     CHECK_NULL_VOID(groupManager);
350     auto eventHub = frameNode->GetEventHub<CheckBoxEventHub>();
351     CHECK_NULL_VOID(eventHub);
352     auto group = eventHub->GetGroupName() + currentNavId_.value_or(groupManager->GetLastNavId());
353     groupManager->RemoveCheckBoxFromGroup(group, frameNode->GetId());
354     auto groupNode = groupManager->GetCheckboxGroup(group);
355     CHECK_NULL_VOID(groupNode);
356     auto checkboxList = groupManager->GetCheckboxList(group);
357     UpdateCheckBoxGroupStatus(groupNode, checkboxList);
358 }
359 
CheckPageNode()360 void CheckBoxPattern::CheckPageNode()
361 {
362     if (Container::IsInSubContainer()) {
363         return;
364     }
365     auto host = GetHost();
366     CHECK_NULL_VOID(host);
367     auto prePageId = GetPrePageId();
368     auto pipelineContext = GetContext();
369     CHECK_NULL_VOID(pipelineContext);
370     auto stageManager = pipelineContext->GetStageManager();
371     CHECK_NULL_VOID(stageManager);
372     auto pageNode = stageManager->GetPageById(host->GetPageId());
373     CHECK_NULL_VOID(pageNode);
374     if (pageNode->GetId() != prePageId) {
375         auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
376         CHECK_NULL_VOID(pageEventHub);
377         auto groupManager = pageEventHub->GetGroupManager();
378         CHECK_NULL_VOID(groupManager);
379         groupManager_ = groupManager;
380         auto group = GetGroupNameWithNavId();
381         groupManager->AddCheckBoxToGroup(group, host);
382         SetPrePageId(pageNode->GetId());
383     }
384 }
385 
UpdateState()386 void CheckBoxPattern::UpdateState()
387 {
388     auto host = GetHost();
389     CHECK_NULL_VOID(host);
390     auto pipelineContext = GetContext();
391     CHECK_NULL_VOID(pipelineContext);
392     auto groupManager = GetGroupManager();
393     CHECK_NULL_VOID(groupManager);
394     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
395     CHECK_NULL_VOID(paintProperty);
396     auto preGroup = GetPreGroup();
397     auto group = GetGroupNameWithNavId();
398     if (!preGroup.has_value()) {
399         groupManager->AddCheckBoxToGroup(group, host);
400         SetPrePageIdToLastPageId();
401         auto callback = [weak = WeakClaim(this)]() {
402             auto checkbox = weak.Upgrade();
403             if (checkbox) {
404                 checkbox->CheckPageNode();
405                 checkbox->CheckBoxGroupIsTrue();
406             }
407         };
408         pipelineContext->AddBuildFinishCallBack(callback);
409         if (paintProperty->HasCheckBoxSelect()) {
410             auto isSelected = paintProperty->GetCheckBoxSelectValue();
411             SetLastSelect(isSelected);
412         }
413         isFirstCreated_ = false;
414         SetPreGroup(group);
415         return;
416     }
417     if (preGroup.has_value() && preGroup.value() != group) {
418         groupManager->RemoveCheckBoxFromGroup(preGroup.value(), host->GetId());
419         groupManager->AddCheckBoxToGroup(group, host);
420         SetPrePageIdToLastPageId();
421     }
422     SetPreGroup(group);
423     ChangeSelfStatusAndNotify(paintProperty);
424     auto groupNode = groupManager->GetCheckboxGroup(group);
425     CHECK_NULL_VOID(groupNode);
426     auto checkboxList = groupManager->GetCheckboxList(group);
427     UpdateCheckBoxGroupStatus(groupNode, checkboxList);
428 }
429 
ChangeSelfStatusAndNotify(const RefPtr<CheckBoxPaintProperty> & paintProperty)430 void CheckBoxPattern::ChangeSelfStatusAndNotify(const RefPtr<CheckBoxPaintProperty>& paintProperty)
431 {
432     auto host = GetHost();
433     CHECK_NULL_VOID(host);
434     bool isSelected = false;
435     if (paintProperty->HasCheckBoxSelect()) {
436         isSelected = paintProperty->GetCheckBoxSelectValue();
437         if (lastSelect_ != isSelected) {
438             UpdateUIStatus(isSelected);
439             SetLastSelect(isSelected);
440             auto checkboxEventHub = GetEventHub<CheckBoxEventHub>();
441             CHECK_NULL_VOID(checkboxEventHub);
442             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkbox node %{public}d update change event %{public}d",
443                 host->GetId(), isSelected);
444             checkboxEventHub->UpdateChangeEvent(isSelected);
445         }
446     }
447     StartCustomNodeAnimation(isSelected);
448     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
449     FireBuilder();
450 }
451 
StartEnterAnimation()452 void CheckBoxPattern::StartEnterAnimation()
453 {
454     AnimationOption option;
455     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
456     option.SetDuration(DEFAULT_CHECKBOX_ANIMATION_DURATION);
457     CHECK_NULL_VOID(builderNode_);
458     const auto& renderContext = builderNode_->GetRenderContext();
459     CHECK_NULL_VOID(renderContext);
460     renderContext->UpdateOpacity(0);
461     const auto& layoutProperty = builderNode_->GetLayoutProperty();
462     CHECK_NULL_VOID(layoutProperty);
463     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
464     const auto& eventHub = builderNode_->GetEventHub<EventHub>();
465     if (eventHub) {
466         eventHub->SetEnabled(true);
467     }
468     AnimationUtils::Animate(
469         option,
470         [&]() {
471             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "check enter animation");
472             renderContext->UpdateOpacity(1);
473         },
474         nullptr);
475 }
476 
StartExitAnimation()477 void CheckBoxPattern::StartExitAnimation()
478 {
479     AnimationOption option;
480     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
481     option.SetDuration(DEFAULT_CHECKBOX_ANIMATION_DURATION);
482     CHECK_NULL_VOID(builderNode_);
483     const auto& renderContext = builderNode_->GetRenderContext();
484     CHECK_NULL_VOID(renderContext);
485     AnimationUtils::Animate(
486         option,
487         [&]() {
488             TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "check exit animation");
489             renderContext->UpdateOpacity(0);
490         },
491         nullptr);
492     const auto& eventHub = builderNode_->GetEventHub<EventHub>();
493     if (eventHub) {
494         eventHub->SetEnabled(false);
495     }
496 }
497 
LoadBuilder()498 void CheckBoxPattern::LoadBuilder()
499 {
500     RefPtr<UINode> customNode;
501     if (builder_.has_value()) {
502         auto host = GetHost();
503         CHECK_NULL_VOID(host);
504         if (builderNode_) {
505             host->RemoveChildAndReturnIndex(builderNode_);
506         }
507         NG::ScopedViewStackProcessor builderViewStackProcessor;
508         builder_.value()();
509         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
510         CHECK_NULL_VOID(customNode);
511         builderNode_ = AceType::DynamicCast<FrameNode>(customNode);
512         CHECK_NULL_VOID(builderNode_);
513         builderNode_->MountToParent(host);
514         host->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
515     }
516 }
517 
StartCustomNodeAnimation(bool select)518 void CheckBoxPattern::StartCustomNodeAnimation(bool select)
519 {
520     if (!isFirstCreated_ && builder_.has_value()) {
521         if (select) {
522             StartEnterAnimation();
523         } else {
524             StartExitAnimation();
525         }
526     }
527 }
528 
UpdateCheckBoxGroupStatus(RefPtr<FrameNode> checkBoxGroupNode,const std::list<RefPtr<FrameNode>> & list)529 void CheckBoxPattern::UpdateCheckBoxGroupStatus(
530     RefPtr<FrameNode> checkBoxGroupNode, const std::list<RefPtr<FrameNode>>& list)
531 {
532     std::vector<std::string> vec;
533     bool haveCheckBoxSelected = false;
534     bool isAllCheckBoxSelected = true;
535     for (auto node : list) {
536         if (!node) {
537             continue;
538         }
539         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
540         CHECK_NULL_VOID(paintProperty);
541         if (paintProperty->GetCheckBoxSelectValue(false)) {
542             auto eventHub = node->GetEventHub<CheckBoxEventHub>();
543             CHECK_NULL_VOID(eventHub);
544             vec.push_back(eventHub->GetName());
545             haveCheckBoxSelected = true;
546         } else {
547             isAllCheckBoxSelected = false;
548         }
549     }
550     ChangeGroupStatusAndNotify(checkBoxGroupNode, vec, haveCheckBoxSelected, isAllCheckBoxSelected);
551 }
552 
ChangeGroupStatusAndNotify(const RefPtr<FrameNode> & checkBoxGroupNode,const std::vector<std::string> & vec,bool haveCheckBoxSelected,bool isAllCheckBoxSelected)553 void CheckBoxPattern::ChangeGroupStatusAndNotify(const RefPtr<FrameNode>& checkBoxGroupNode,
554     const std::vector<std::string>& vec, bool haveCheckBoxSelected, bool isAllCheckBoxSelected)
555 {
556     CHECK_NULL_VOID(checkBoxGroupNode);
557     auto groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
558     CHECK_NULL_VOID(groupPaintProperty);
559     auto pattern = checkBoxGroupNode->GetPattern<CheckBoxGroupPattern>();
560     CHECK_NULL_VOID(pattern);
561     auto preStatus = groupPaintProperty->GetSelectStatus();
562     if (haveCheckBoxSelected) {
563         if (isAllCheckBoxSelected) {
564             groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
565             pattern->UpdateUIStatus(true);
566         } else {
567             groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::PART);
568             pattern->ResetUIStatus();
569         }
570     } else {
571         groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
572         pattern->UpdateUIStatus(false);
573     }
574     checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
575     auto status = groupPaintProperty->GetSelectStatus();
576     if (preStatus != status && (preStatus == CheckBoxGroupPaintProperty::SelectStatus::ALL ||
577                                    status == CheckBoxGroupPaintProperty::SelectStatus::ALL)) {
578         pattern->SetSkipFlag(true);
579     }
580     CheckboxGroupResult groupResult(vec, int(status));
581     auto eventHub = checkBoxGroupNode->GetEventHub<CheckBoxGroupEventHub>();
582     CHECK_NULL_VOID(eventHub);
583     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "update checkboxgroup result %d", groupResult.GetStatus());
584     eventHub->UpdateChangeEvent(&groupResult);
585 }
586 
CheckBoxGroupIsTrue()587 void CheckBoxPattern::CheckBoxGroupIsTrue()
588 {
589     auto host = GetHost();
590     CHECK_NULL_VOID(host);
591     auto groupManager = GetGroupManager();
592     CHECK_NULL_VOID(groupManager);
593     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
594     CHECK_NULL_VOID(paintProperty);
595     auto group = GetGroupNameWithNavId();
596     RefPtr<FrameNode> checkBoxGroupNode = groupManager->GetCheckboxGroup(group);
597     CHECK_NULL_VOID(checkBoxGroupNode);
598     std::vector<std::string> vec;
599     bool allSelectIsNull = true;
600     const auto& list = groupManager->GetCheckboxList(group);
601     for (auto node : list) {
602         if (!node) {
603             continue;
604         }
605         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
606         CHECK_NULL_VOID(paintProperty);
607         if (paintProperty->HasCheckBoxSelect()) {
608             allSelectIsNull = false;
609         } else {
610             paintProperty->UpdateCheckBoxSelect(false);
611         }
612     }
613     const auto& groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
614     CHECK_NULL_VOID(groupPaintProperty);
615     if (!groupManager->GetCheckboxGroupIsChange(group) && groupPaintProperty->GetIsCheckBoxCallbackDealed()) {
616         return;
617     }
618     // All checkboxes do not set select status.
619     if (allSelectIsNull && groupPaintProperty->GetCheckBoxGroupSelectValue(false)) {
620         InitCheckBoxStatusByGroup(checkBoxGroupNode, groupPaintProperty, list);
621     }
622     // Some checkboxes set select status.
623     if (!allSelectIsNull) {
624         UpdateCheckBoxGroupStatus(checkBoxGroupNode, list);
625     }
626     groupPaintProperty->SetIsCheckBoxCallbackDealed(true);
627     groupManager->SetCheckboxGroupIsChange(group, false);
628 }
629 
InitCheckBoxStatusByGroup(RefPtr<FrameNode> checkBoxGroupNode,const RefPtr<CheckBoxGroupPaintProperty> & groupPaintProperty,const std::list<RefPtr<FrameNode>> & list)630 void CheckBoxPattern::InitCheckBoxStatusByGroup(RefPtr<FrameNode> checkBoxGroupNode,
631     const RefPtr<CheckBoxGroupPaintProperty>& groupPaintProperty, const std::list<RefPtr<FrameNode>>& list)
632 {
633     if (groupPaintProperty->GetCheckBoxGroupSelectValue(false)) {
634         groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
635         groupPaintProperty->UpdateCheckBoxGroupSelect(true);
636         checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
637         for (auto node : list) {
638             if (!node) {
639                 continue;
640             }
641             auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
642             CHECK_NULL_VOID(paintProperty);
643             paintProperty->UpdateCheckBoxSelect(true);
644             auto checkBoxPattern = node->GetPattern<CheckBoxPattern>();
645             CHECK_NULL_VOID(checkBoxPattern);
646             checkBoxPattern->StartCustomNodeAnimation(true);
647             checkBoxPattern->UpdateUIStatus(true);
648             checkBoxPattern->SetLastSelect(true);
649         }
650     }
651 }
652 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)653 void CheckBoxPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
654 {
655     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
656         auto pattern = wp.Upgrade();
657         if (pattern) {
658             pattern->GetInnerFocusPaintRect(paintRect);
659         }
660     };
661     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
662 }
663 
GetInnerFocusPaintRect(RoundRect & paintRect)664 void CheckBoxPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
665 {
666     auto host = GetHost();
667     CHECK_NULL_VOID(host);
668     auto* pipelineContext = host->GetContextWithCheck();
669     CHECK_NULL_VOID(pipelineContext);
670     auto checkBoxTheme = pipelineContext->GetTheme<CheckboxTheme>();
671     CHECK_NULL_VOID(checkBoxTheme);
672     auto borderRadius = checkBoxTheme->GetFocusRadius().ConvertToPx();
673     auto focusPaintPadding = checkBoxTheme->GetFocusPaintPadding().ConvertToPx();
674     float originX = offset_.GetX() - focusPaintPadding;
675     float originY = offset_.GetY() - focusPaintPadding;
676     float width = size_.Width() + 2 * focusPaintPadding;
677     float height = size_.Height() + 2 * focusPaintPadding;
678     paintRect.SetRect({ originX, originY, width, height });
679     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, borderRadius, borderRadius);
680     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, borderRadius, borderRadius);
681     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, borderRadius, borderRadius);
682     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, borderRadius, borderRadius);
683 }
684 
GetFocusPattern() const685 FocusPattern CheckBoxPattern::GetFocusPattern() const
686 {
687     auto host = GetHost();
688     CHECK_NULL_RETURN(host, FocusPattern());
689     auto* pipeline = host->GetContextWithCheck();
690     CHECK_NULL_RETURN(pipeline, FocusPattern());
691     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
692     CHECK_NULL_RETURN(checkBoxTheme, FocusPattern());
693     auto activeColor = checkBoxTheme->GetActiveColor();
694     FocusPaintParam focusPaintParam;
695     focusPaintParam.SetPaintColor(activeColor);
696     return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
697 }
698 
699 // Set the default hot zone for the component.
AddHotZoneRect()700 void CheckBoxPattern::AddHotZoneRect()
701 {
702     hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
703     hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
704     hotZoneSize_.SetWidth(size_.Width() + 2 * hotZoneHorizontalPadding_.ConvertToPx());
705     hotZoneSize_.SetHeight(size_.Height() + 2 * hotZoneVerticalPadding_.ConvertToPx());
706     DimensionRect hotZoneRegion;
707     hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
708     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
709     auto host = GetHost();
710     CHECK_NULL_VOID(host);
711     auto gestureHub = host->GetOrCreateGestureEventHub();
712     CHECK_NULL_VOID(gestureHub);
713     std::vector<DimensionRect> hotZoneRegions;
714     hotZoneRegions.emplace_back(hotZoneRegion);
715     gestureHub->SetResponseRegion(hotZoneRegions);
716 }
717 
RemoveLastHotZoneRect() const718 void CheckBoxPattern::RemoveLastHotZoneRect() const
719 {
720     auto host = GetHost();
721     CHECK_NULL_VOID(host);
722     host->RemoveLastHotZoneRect();
723 }
724 
ProvideRestoreInfo()725 std::string CheckBoxPattern::ProvideRestoreInfo()
726 {
727     auto jsonObj = JsonUtil::Create(true);
728     auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
729     CHECK_NULL_RETURN(checkBoxPaintProperty, "");
730     jsonObj->Put("isOn", checkBoxPaintProperty->GetCheckBoxSelect().value_or(false));
731     return jsonObj->ToString();
732 }
733 
OnRestoreInfo(const std::string & restoreInfo)734 void CheckBoxPattern::OnRestoreInfo(const std::string& restoreInfo)
735 {
736     auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
737     CHECK_NULL_VOID(checkBoxPaintProperty);
738     auto info = JsonUtil::ParseJsonString(restoreInfo);
739     if (!info->IsValid() || !info->IsObject()) {
740         return;
741     }
742     auto jsonCheckBoxSelect = info->GetValue("isOn");
743     checkBoxPaintProperty->UpdateCheckBoxSelect(jsonCheckBoxSelect->GetBool());
744 }
745 
SetCheckBoxSelect(bool select)746 void CheckBoxPattern::SetCheckBoxSelect(bool select)
747 {
748     auto host = GetHost();
749     CHECK_NULL_VOID(host);
750     auto eventHub = host->GetEventHub<EventHub>();
751     CHECK_NULL_VOID(eventHub);
752     auto enabled = eventHub->IsEnabled();
753     if (!enabled) {
754         return;
755     }
756     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
757     CHECK_NULL_VOID(paintProperty);
758     paintProperty->UpdateCheckBoxSelect(select);
759     UpdateState();
760     OnModifyDone();
761 }
762 
FireBuilder()763 void CheckBoxPattern::FireBuilder()
764 {
765     auto host = GetHost();
766     CHECK_NULL_VOID(host);
767     if (!makeFunc_.has_value() && !toggleMakeFunc_.has_value()) {
768         host->RemoveChildAndReturnIndex(contentModifierNode_);
769         contentModifierNode_ = nullptr;
770         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
771         return;
772     }
773     auto node = BuildContentModifierNode();
774     if (contentModifierNode_ == node) {
775         return;
776     }
777     auto renderContext = host->GetRenderContext();
778     CHECK_NULL_VOID(renderContext);
779     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
780     host->RemoveChildAndReturnIndex(contentModifierNode_);
781     contentModifierNode_ = node;
782     CHECK_NULL_VOID(contentModifierNode_);
783     host->AddChild(contentModifierNode_, 0);
784     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
785 }
786 
BuildContentModifierNode()787 RefPtr<FrameNode> CheckBoxPattern::BuildContentModifierNode()
788 {
789     if (!makeFunc_.has_value() && !toggleMakeFunc_.has_value()) {
790         return nullptr;
791     }
792     auto host = GetHost();
793     CHECK_NULL_RETURN(host, nullptr);
794     auto eventHub = host->GetEventHub<CheckBoxEventHub>();
795     CHECK_NULL_RETURN(eventHub, nullptr);
796     auto name = eventHub->GetName();
797     auto enabled = eventHub->IsEnabled();
798     auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
799     CHECK_NULL_RETURN(paintProperty, nullptr);
800     bool isSelected = false;
801     if (paintProperty->HasCheckBoxSelect()) {
802         isSelected = paintProperty->GetCheckBoxSelectValue();
803     } else {
804         isSelected = false;
805     }
806     if (host->GetHostTag() == V2::CHECKBOX_ETS_TAG && toggleMakeFunc_.has_value()) {
807         return (toggleMakeFunc_.value())(ToggleConfiguration(enabled, isSelected));
808     }
809     CheckBoxConfiguration checkBoxConfiguration(name, isSelected, enabled);
810     return (makeFunc_.value())(checkBoxConfiguration);
811 }
812 
UpdatePaintPropertyBySettingData(RefPtr<CheckBoxPaintProperty> paintProp)813 void CheckBoxPattern::UpdatePaintPropertyBySettingData(RefPtr<CheckBoxPaintProperty> paintProp)
814 {
815     if (checkboxSettingData_.selectedColor.has_value()) {
816         paintProp->UpdateCheckBoxSelectedColor(checkboxSettingData_.selectedColor.value());
817     }
818     if (checkboxSettingData_.unselectedColor.has_value()) {
819         paintProp->UpdateCheckBoxUnSelectedColor(checkboxSettingData_.unselectedColor.value());
820     }
821     if (checkboxSettingData_.strokeColor.has_value()) {
822         paintProp->UpdateCheckBoxCheckMarkColor(checkboxSettingData_.strokeColor.value());
823     }
824 }
825 
OnColorConfigurationUpdate()826 void CheckBoxPattern::OnColorConfigurationUpdate()
827 {
828     auto host = GetHost();
829     CHECK_NULL_VOID(host);
830     auto* pipeline = host->GetContextWithCheck();
831     CHECK_NULL_VOID(pipeline);
832     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
833     CHECK_NULL_VOID(checkBoxTheme);
834     auto checkBoxPaintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
835     CHECK_NULL_VOID(checkBoxPaintProperty);
836     checkBoxPaintProperty->UpdateCheckBoxSelectedColor(checkBoxTheme->GetActiveColor());
837     checkBoxPaintProperty->UpdateCheckBoxUnSelectedColor(checkBoxTheme->GetInactiveColor());
838     checkBoxPaintProperty->UpdateCheckBoxCheckMarkColor(checkBoxTheme->GetPointColor());
839     UpdatePaintPropertyBySettingData(checkBoxPaintProperty);
840     host->MarkModifyDone();
841     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
842 }
843 
SetPrePageIdToLastPageId()844 void CheckBoxPattern::SetPrePageIdToLastPageId()
845 {
846     if (!Container::IsInSubContainer()) {
847         auto pipelineContext = PipelineContext::GetCurrentContext();
848         CHECK_NULL_VOID(pipelineContext);
849         auto stageManager = pipelineContext->GetStageManager();
850         CHECK_NULL_VOID(stageManager);
851         auto pageNode = stageManager->GetLastPage();
852         CHECK_NULL_VOID(pageNode);
853         SetPrePageId(pageNode->GetId());
854     }
855 }
856 
OnAttachToMainTree()857 void CheckBoxPattern::OnAttachToMainTree()
858 {
859     auto host = GetHost();
860     CHECK_NULL_VOID(host);
861     auto groupManager = GetGroupManager();
862     CHECK_NULL_VOID(groupManager);
863     auto parent = host->GetParent();
864     while (parent) {
865         if (parent->GetTag() == V2::NAVDESTINATION_CONTENT_ETS_TAG) {
866             currentNavId_ = std::to_string(parent->GetId());
867             groupManager->SetLastNavId(currentNavId_);
868             UpdateState();
869             return;
870         }
871         parent = parent->GetParent();
872     }
873     if (!currentNavId_.value_or("").empty()) {
874         currentNavId_ = "";
875         groupManager->SetLastNavId(std::nullopt);
876         UpdateState();
877     }
878 }
879 
GetGroupNameWithNavId()880 std::string CheckBoxPattern::GetGroupNameWithNavId()
881 {
882     auto host = GetHost();
883     CHECK_NULL_RETURN(host, "");
884     auto eventHub = host->GetEventHub<CheckBoxEventHub>();
885     CHECK_NULL_RETURN(eventHub, "");
886     if (currentNavId_.has_value()) {
887         return eventHub->GetGroupName() + currentNavId_.value();
888     }
889     auto groupManager = GetGroupManager();
890     CHECK_NULL_RETURN(groupManager, eventHub->GetGroupName());
891     return eventHub->GetGroupName() + groupManager->GetLastNavId();
892 }
893 
GetGroupManager()894 RefPtr<GroupManager> CheckBoxPattern::GetGroupManager()
895 {
896     auto manager = groupManager_.Upgrade();
897     if (manager) {
898         return manager;
899     }
900     groupManager_ = GroupManager::GetGroupManager();
901     return groupManager_.Upgrade();
902 }
903 } // namespace OHOS::Ace::NG
904