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 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_pattern.h"
16 
17 #include "core/common/recorder/node_data_cache.h"
18 #include "core/components/checkable/checkable_component.h"
19 #include "core/components_ng/pattern/checkbox/checkbox_paint_property.h"
20 #include "core/components_ng/pattern/checkbox/checkbox_pattern.h"
21 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_paint_property.h"
22 #include "core/components_ng/pattern/stage/page_event_hub.h"
23 #include "core/components_ng/property/calc_length.h"
24 #include "core/components_ng/property/property.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/event/touch_event.h"
27 #include "core/pipeline_ng/pipeline_context.h"
28 
29 namespace OHOS::Ace::NG {
30 namespace {
31 const Color ITEM_FILL_COLOR = Color::TRANSPARENT;
32 }
33 
OnAttachToFrameNode()34 void CheckBoxGroupPattern::OnAttachToFrameNode()
35 {
36     auto host = GetHost();
37     CHECK_NULL_VOID(host);
38     host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
39 }
40 
OnDetachFromFrameNode(FrameNode * frameNode)41 void CheckBoxGroupPattern::OnDetachFromFrameNode(FrameNode* frameNode)
42 {
43     CHECK_NULL_VOID(frameNode);
44     auto groupManager = GetGroupManager();
45     CHECK_NULL_VOID(groupManager);
46     groupManager->RemoveCheckBoxGroup(GetGroupNameWithNavId(), frameNode->GetId());
47 }
48 
OnModifyDone()49 void CheckBoxGroupPattern::OnModifyDone()
50 {
51     Pattern::OnModifyDone();
52     UpdateState();
53     auto host = GetHost();
54     CHECK_NULL_VOID(host);
55     auto pipeline = PipelineBase::GetCurrentContext();
56     CHECK_NULL_VOID(pipeline);
57     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
58     CHECK_NULL_VOID(checkBoxTheme);
59     auto layoutProperty = host->GetLayoutProperty();
60     CHECK_NULL_VOID(layoutProperty);
61     if (!layoutProperty->GetMarginProperty()) {
62         MarginProperty margin;
63         margin.left = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
64         margin.right = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
65         margin.top = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
66         margin.bottom = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
67         layoutProperty->UpdateMargin(margin);
68     }
69     hotZoneHorizontalPadding_ = checkBoxTheme->GetHotZoneHorizontalPadding();
70     hotZoneVerticalPadding_ = checkBoxTheme->GetHotZoneVerticalPadding();
71     InitClickEvent();
72     InitTouchEvent();
73     InitMouseEvent();
74     auto focusHub = host->GetFocusHub();
75     CHECK_NULL_VOID(focusHub);
76     InitOnKeyEvent(focusHub);
77     SetAccessibilityAction();
78 }
79 
SetAccessibilityAction()80 void CheckBoxGroupPattern::SetAccessibilityAction()
81 {
82     auto host = GetHost();
83     CHECK_NULL_VOID(host);
84     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
85     CHECK_NULL_VOID(accessibilityProperty);
86     accessibilityProperty->SetActionSelect([weakPtr = WeakClaim(this)]() {
87         const auto& pattern = weakPtr.Upgrade();
88         CHECK_NULL_VOID(pattern);
89         pattern->UpdateSelectStatus(true);
90     });
91 
92     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
93         const auto& pattern = weakPtr.Upgrade();
94         CHECK_NULL_VOID(pattern);
95         pattern->UpdateSelectStatus(false);
96     });
97 }
98 
UpdateSelectStatus(bool isSelected)99 void CheckBoxGroupPattern::UpdateSelectStatus(bool isSelected)
100 {
101     auto host = GetHost();
102     CHECK_NULL_VOID(host);
103     auto context = host->GetRenderContext();
104     CHECK_NULL_VOID(context);
105     MarkIsSelected(isSelected);
106     context->OnMouseSelectUpdate(isSelected, ITEM_FILL_COLOR, ITEM_FILL_COLOR);
107 }
108 
MarkIsSelected(bool isSelected)109 void CheckBoxGroupPattern::MarkIsSelected(bool isSelected)
110 {
111     if (updateFlag_ == isSelected) {
112         return;
113     }
114     updateFlag_ = isSelected;
115     auto eventHub = GetEventHub<CheckBoxGroupEventHub>();
116     std::vector<std::string> vec;
117     CheckboxGroupResult groupResult(vec, int(isSelected));
118     eventHub->UpdateChangeEvent(&groupResult);
119     auto host = GetHost();
120     CHECK_NULL_VOID(host);
121     if (isSelected) {
122         eventHub->UpdateCurrentUIState(UI_STATE_SELECTED);
123         host->OnAccessibilityEvent(AccessibilityEventType::SELECTED);
124     } else {
125         eventHub->ResetCurrentUIState(UI_STATE_SELECTED);
126         host->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
127     }
128 }
129 
InitClickEvent()130 void CheckBoxGroupPattern::InitClickEvent()
131 {
132     if (clickListener_) {
133         return;
134     }
135     auto host = GetHost();
136     CHECK_NULL_VOID(host);
137     auto gesture = host->GetOrCreateGestureEventHub();
138     CHECK_NULL_VOID(gesture);
139     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
140         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "checkboxgroup onclick");
141         auto checkboxPattern = weak.Upgrade();
142         CHECK_NULL_VOID(checkboxPattern);
143         checkboxPattern->OnClick();
144     };
145     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
146     gesture->AddClickEvent(clickListener_);
147 }
148 
InitTouchEvent()149 void CheckBoxGroupPattern::InitTouchEvent()
150 {
151     if (touchListener_) {
152         return;
153     }
154     auto host = GetHost();
155     CHECK_NULL_VOID(host);
156     auto gesture = host->GetOrCreateGestureEventHub();
157     CHECK_NULL_VOID(gesture);
158     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
159         auto checkboxPattern = weak.Upgrade();
160         CHECK_NULL_VOID(checkboxPattern);
161         if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
162             checkboxPattern->OnTouchDown();
163         }
164         if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
165             info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
166             checkboxPattern->OnTouchUp();
167         }
168     };
169     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
170     gesture->AddTouchEvent(touchListener_);
171 }
172 
InitMouseEvent()173 void CheckBoxGroupPattern::InitMouseEvent()
174 {
175     if (mouseEvent_) {
176         return;
177     }
178     auto host = GetHost();
179     CHECK_NULL_VOID(host);
180     auto gesture = host->GetOrCreateGestureEventHub();
181     CHECK_NULL_VOID(gesture);
182     auto eventHub = host->GetEventHub<CheckBoxGroupEventHub>();
183     auto inputHub = eventHub->GetOrCreateInputEventHub();
184 
185     auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
186         auto pattern = weak.Upgrade();
187         if (pattern) {
188             pattern->HandleMouseEvent(isHover);
189         }
190     };
191     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
192     inputHub->AddOnHoverEvent(mouseEvent_);
193 }
194 
HandleMouseEvent(bool isHover)195 void CheckBoxGroupPattern::HandleMouseEvent(bool isHover)
196 {
197     isHover_ = isHover;
198     if (isHover) {
199         touchHoverType_ = TouchHoverAnimationType::HOVER;
200     } else {
201         touchHoverType_ = TouchHoverAnimationType::NONE;
202     }
203     auto host = GetHost();
204     CHECK_NULL_VOID(host);
205     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
206 }
207 
OnClick()208 void CheckBoxGroupPattern::OnClick()
209 {
210     auto host = GetHost();
211     CHECK_NULL_VOID(host);
212     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
213     CHECK_NULL_VOID(paintProperty);
214     bool isSelected = false;
215     auto status = paintProperty->GetSelectStatus();
216     isSelected = status == CheckBoxGroupPaintProperty::SelectStatus::NONE;
217     paintProperty->UpdateCheckBoxGroupSelect(isSelected);
218     updateFlag_ = true;
219     UpdateState();
220 }
221 
OnTouchDown()222 void CheckBoxGroupPattern::OnTouchDown()
223 {
224     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "checkboxgroup touch down %{public}d", isHover_);
225     if (isHover_) {
226         touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
227     } else {
228         touchHoverType_ = TouchHoverAnimationType::PRESS;
229     }
230     auto host = GetHost();
231     CHECK_NULL_VOID(host);
232     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
233 }
234 
OnTouchUp()235 void CheckBoxGroupPattern::OnTouchUp()
236 {
237     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "checkboxgroup touch up %{public}d", isHover_);
238     if (isHover_) {
239         touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
240     } else {
241         touchHoverType_ = TouchHoverAnimationType::NONE;
242     }
243     auto host = GetHost();
244     CHECK_NULL_VOID(host);
245     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
246 }
247 
UpdateUnSelect()248 void CheckBoxGroupPattern::UpdateUnSelect()
249 {
250     auto host = GetHost();
251     CHECK_NULL_VOID(host);
252     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
253     CHECK_NULL_VOID(paintProperty);
254     if (paintProperty->GetSelectStatus() == CheckBoxGroupPaintProperty::SelectStatus::NONE) {
255         uiStatus_ = UIStatus::UNSELECTED;
256         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
257     }
258 }
259 
UpdateUIStatus(bool check)260 void CheckBoxGroupPattern::UpdateUIStatus(bool check)
261 {
262     auto host = GetHost();
263     CHECK_NULL_VOID(host);
264     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
265     CHECK_NULL_VOID(paintProperty);
266     auto selectStatus = paintProperty->GetSelectStatus();
267     TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "checkboxgroup update status %{public}d %{public}d", check, selectStatus);
268     if (selectStatus == CheckBoxGroupPaintProperty::SelectStatus::PART) {
269         uiStatus_ = check ? UIStatus::PART_TO_ON : UIStatus::PART_TO_OFF;
270     } else {
271         uiStatus_ = check ? UIStatus::OFF_TO_ON : UIStatus::ON_TO_OFF;
272     }
273     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
274 }
275 
UpdateState()276 void CheckBoxGroupPattern::UpdateState()
277 {
278     auto host = GetHost();
279     CHECK_NULL_VOID(host);
280     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
281         UpdateCheckBoxStyle();
282     }
283     auto eventHub = host->GetEventHub<CheckBoxGroupEventHub>();
284     CHECK_NULL_VOID(eventHub);
285     auto preGroup = GetPreGroup();
286     if (!preGroup.has_value()) {
287         InitPreGroup();
288         return;
289     }
290     auto groupManager = GetGroupManager();
291     CHECK_NULL_VOID(groupManager);
292     auto group = GetGroupNameWithNavId();
293     if (preGroup.value() != group) {
294         groupManager->RemoveCheckBoxGroup(preGroup.value(), host->GetId());
295         groupManager->AddCheckBoxGroup(group, host);
296         SetPreGroup(group);
297         return;
298     }
299     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
300     CHECK_NULL_VOID(paintProperty);
301     if (!paintProperty->HasCheckBoxGroupSelect()) {
302         return;
303     }
304     bool isSelected = paintProperty->GetCheckBoxGroupSelectValue();
305     paintProperty->ResetCheckBoxGroupSelect();
306     if (eventHub->HasChangeEvent() && skipFlag_) {
307         skipFlag_ = false;
308         return;
309     }
310 
311     // Setting selectAll to false when clicked requires processing, changing selectAll to false dynamically does
312     // not require processing
313     if (updateFlag_ || isSelected) {
314         if (GetIsAddToMap()) {
315             UpdateGroupCheckStatus(host, isSelected);
316         } else {
317             UpdateRepeatedGroupStatus(host, isSelected);
318         }
319     }
320     updateFlag_ = false;
321 }
322 
InitPreGroup()323 void CheckBoxGroupPattern::InitPreGroup()
324 {
325     auto host = GetHost();
326     CHECK_NULL_VOID(host);
327     auto groupManager = GetGroupManager();
328     CHECK_NULL_VOID(groupManager);
329     auto group = GetGroupNameWithNavId();
330     groupManager->AddCheckBoxGroup(group, host);
331     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
332     CHECK_NULL_VOID(paintProperty);
333     if (paintProperty->GetCheckBoxGroupSelect().value_or(false)) {
334         paintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
335         UpdateUIStatus(true);
336         initSelected_ = true;
337     }
338     isFirstCreated_ = false;
339     SetPreGroup(group);
340 }
341 
OnAfterModifyDone()342 void CheckBoxGroupPattern::OnAfterModifyDone()
343 {
344     auto host = GetHost();
345     CHECK_NULL_VOID(host);
346     auto inspectorId = host->GetInspectorId().value_or("");
347     if (inspectorId.empty()) {
348         return;
349     }
350 
351     auto eventHub = host->GetEventHub<CheckBoxGroupEventHub>();
352     CHECK_NULL_VOID(eventHub);
353     std::vector<std::string> vec;
354     if (initSelected_) {
355         auto groupManager = GetGroupManager();
356         CHECK_NULL_VOID(groupManager);
357         auto list = groupManager->GetCheckboxList(GetGroupNameWithNavId());
358         for (auto node : list) {
359             if (!node) {
360                 continue;
361             }
362             auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
363             CHECK_NULL_VOID(paintProperty);
364             auto eventHub = node->GetEventHub<CheckBoxEventHub>();
365             CHECK_NULL_VOID(eventHub);
366             vec.push_back(eventHub->GetName());
367         }
368     }
369     Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, eventHub->GetGroupName(), vec);
370 }
371 
UpdateGroupCheckStatus(const RefPtr<FrameNode> & frameNode,bool select)372 void CheckBoxGroupPattern::UpdateGroupCheckStatus(const RefPtr<FrameNode>& frameNode, bool select)
373 {
374     auto paintProperty = frameNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
375     CHECK_NULL_VOID(paintProperty);
376     auto pattern = frameNode->GetPattern<CheckBoxGroupPattern>();
377     CHECK_NULL_VOID(pattern);
378     pattern->UpdateUIStatus(select);
379     if (select) {
380         paintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
381     } else {
382         paintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
383     }
384     frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
385     UpdateCheckBoxStatus(frameNode, select);
386 }
387 
UpdateCheckBoxStatus(const RefPtr<FrameNode> & frameNode,bool select)388 void CheckBoxGroupPattern::UpdateCheckBoxStatus(const RefPtr<FrameNode>& frameNode, bool select)
389 {
390     auto groupManager = GetGroupManager();
391     CHECK_NULL_VOID(groupManager);
392     auto group = GetGroupNameWithNavId();
393     auto list = groupManager->GetCheckboxList(group);
394     std::vector<std::string> vec;
395     auto status =
396         select ? CheckBoxGroupPaintProperty::SelectStatus::ALL : CheckBoxGroupPaintProperty::SelectStatus::NONE;
397     for (auto && node : list) {
398         if (!node) {
399             continue;
400         }
401         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
402         CHECK_NULL_VOID(paintProperty);
403         auto eventHub = node->GetEventHub<CheckBoxEventHub>();
404         CHECK_NULL_VOID(eventHub);
405         if (select) {
406             vec.push_back(eventHub->GetName());
407         }
408         if (paintProperty->GetCheckBoxSelectValue(false) != select) {
409             paintProperty->UpdateCheckBoxSelect(select);
410             auto pattern = node->GetPattern<CheckBoxPattern>();
411             pattern->StartCustomNodeAnimation(select);
412             pattern->UpdateUIStatus(select);
413             pattern->SetLastSelect(select);
414             eventHub->UpdateChangeEvent(select);
415         }
416     }
417     CheckboxGroupResult groupResult(vec, int(status));
418     auto eventHub = frameNode->GetEventHub<CheckBoxGroupEventHub>();
419     eventHub->UpdateChangeEvent(&groupResult);
420 }
421 
UpdateRepeatedGroupStatus(const RefPtr<FrameNode> & frameNode,bool select)422 void CheckBoxGroupPattern::UpdateRepeatedGroupStatus(const RefPtr<FrameNode>& frameNode, bool select)
423 {
424     std::vector<std::string> vec;
425     auto status =
426         select ? CheckBoxGroupPaintProperty::SelectStatus::ALL : CheckBoxGroupPaintProperty::SelectStatus::NONE;
427     auto pattern = frameNode->GetPattern<CheckBoxGroupPattern>();
428     CHECK_NULL_VOID(pattern);
429     pattern->UpdateUIStatus(select);
430     auto paintProperty = frameNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
431     CHECK_NULL_VOID(paintProperty);
432     paintProperty->SetSelectStatus(
433         select ? CheckBoxGroupPaintProperty::SelectStatus::ALL : CheckBoxGroupPaintProperty::SelectStatus::NONE);
434     auto checkBoxGroupEventHub = GetEventHub<CheckBoxGroupEventHub>();
435     CHECK_NULL_VOID(checkBoxGroupEventHub);
436     frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
437     CheckboxGroupResult groupResult(vec, int(status));
438     auto eventHub = frameNode->GetEventHub<CheckBoxGroupEventHub>();
439     eventHub->UpdateChangeEvent(&groupResult);
440 }
441 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)442 void CheckBoxGroupPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
443 {
444     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
445         auto pattern = wp.Upgrade();
446         if (pattern) {
447             pattern->GetInnerFocusPaintRect(paintRect);
448         }
449     };
450     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
451 }
452 
GetInnerFocusPaintRect(RoundRect & paintRect)453 void CheckBoxGroupPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
454 {
455     auto groupPaintProperty = GetPaintProperty<CheckBoxGroupPaintProperty>();
456     CHECK_NULL_VOID(groupPaintProperty);
457     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
458         auto checkboxGroupStyle = groupPaintProperty->GetCheckBoxGroupSelectedStyleValue(CheckBoxStyle::CIRCULAR_STYLE);
459         if (checkboxGroupStyle == CheckBoxStyle::CIRCULAR_STYLE) {
460             InnerFocusPaintCircle(paintRect);
461             return;
462         }
463     }
464     auto pipelineContext = PipelineBase::GetCurrentContext();
465     CHECK_NULL_VOID(pipelineContext);
466     auto checkBoxTheme = pipelineContext->GetTheme<CheckboxTheme>();
467     CHECK_NULL_VOID(checkBoxTheme);
468     auto borderRadius = checkBoxTheme->GetFocusRadius().ConvertToPx();
469     auto focusPaintPadding = checkBoxTheme->GetFocusPaintPadding().ConvertToPx();
470     float originX = offset_.GetX() - focusPaintPadding;
471     float originY = offset_.GetY() - focusPaintPadding;
472     float width = size_.Width() + 2 * focusPaintPadding;
473     float height = size_.Height() + 2 * focusPaintPadding;
474     paintRect.SetRect({ originX, originY, width, height });
475     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, borderRadius, borderRadius);
476     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, borderRadius, borderRadius);
477     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, borderRadius, borderRadius);
478     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, borderRadius, borderRadius);
479 }
480 
InnerFocusPaintCircle(RoundRect & paintRect)481 void CheckBoxGroupPattern::InnerFocusPaintCircle(RoundRect& paintRect)
482 {
483     auto pipeline = PipelineBase::GetCurrentContext();
484     CHECK_NULL_VOID(pipeline);
485     auto radioTheme = pipeline->GetTheme<CheckboxTheme>();
486     CHECK_NULL_VOID(radioTheme);
487     auto focusPaintPadding = radioTheme->GetFocusPaintPadding().ConvertToPx();
488     float outCircleRadius = size_.Width() / 2 + focusPaintPadding;
489     float originX = offset_.GetX() - focusPaintPadding;
490     float originY = offset_.GetY() - focusPaintPadding;
491     float width = size_.Width() + 2 * focusPaintPadding;
492     float height = size_.Height() + 2 * focusPaintPadding;
493     paintRect.SetRect({ originX, originY, width, height });
494     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, outCircleRadius, outCircleRadius);
495     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, outCircleRadius, outCircleRadius);
496     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, outCircleRadius, outCircleRadius);
497     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, outCircleRadius, outCircleRadius);
498 }
499 
GetFocusPattern() const500 FocusPattern CheckBoxGroupPattern::GetFocusPattern() const
501 {
502     auto pipeline = PipelineBase::GetCurrentContext();
503     CHECK_NULL_RETURN(pipeline, FocusPattern());
504     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
505     CHECK_NULL_RETURN(checkBoxTheme, FocusPattern());
506     auto activeColor = checkBoxTheme->GetActiveColor();
507     FocusPaintParam focusPaintParam;
508     focusPaintParam.SetPaintColor(activeColor);
509     return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
510 }
511 
512 // Set the default hot zone for the component.
AddHotZoneRect()513 void CheckBoxGroupPattern::AddHotZoneRect()
514 {
515     hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
516     hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
517     hotZoneSize_.SetWidth(size_.Width() + 2 * hotZoneHorizontalPadding_.ConvertToPx());
518     hotZoneSize_.SetHeight(size_.Height() + 2 * hotZoneVerticalPadding_.ConvertToPx());
519     DimensionRect hotZoneRegion;
520     hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
521     hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
522     auto host = GetHost();
523     CHECK_NULL_VOID(host);
524     auto gestureHub = host->GetOrCreateGestureEventHub();
525     CHECK_NULL_VOID(gestureHub);
526     std::vector<DimensionRect> hotZoneRegions;
527     hotZoneRegions.emplace_back(hotZoneRegion);
528     gestureHub->SetResponseRegion(hotZoneRegions);
529 }
530 
RemoveLastHotZoneRect() const531 void CheckBoxGroupPattern::RemoveLastHotZoneRect() const
532 {
533     auto host = GetHost();
534     CHECK_NULL_VOID(host);
535     host->RemoveLastHotZoneRect();
536 }
537 
InitializeModifierParam(CheckBoxGroupModifier::Parameters & paintParameters)538 void CheckBoxGroupPattern::InitializeModifierParam(CheckBoxGroupModifier::Parameters& paintParameters)
539 {
540     auto pipeline = PipelineBase::GetCurrentContext();
541     CHECK_NULL_VOID(pipeline);
542     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
543     CHECK_NULL_VOID(checkBoxTheme);
544     paintParameters.borderWidth = checkBoxTheme->GetBorderWidth().ConvertToPx();
545     paintParameters.borderRadius = checkBoxTheme->GetBorderRadius().ConvertToPx();
546     paintParameters.checkStroke = checkBoxTheme->GetCheckStroke().ConvertToPx();
547     paintParameters.pointColor = checkBoxTheme->GetPointColor();
548     paintParameters.activeColor = checkBoxTheme->GetActiveColor();
549     paintParameters.inactiveColor = checkBoxTheme->GetInactiveColor();
550     paintParameters.inactivePointColor = checkBoxTheme->GetInactivePointColor();
551     paintParameters.shadowColor = checkBoxTheme->GetShadowColor();
552     paintParameters.clickEffectColor = checkBoxTheme->GetClickEffectColor();
553     paintParameters.hoverColor = checkBoxTheme->GetHoverColor();
554     paintParameters.hoverRadius = checkBoxTheme->GetHoverRadius();
555     paintParameters.hotZoneHorizontalPadding = checkBoxTheme->GetHotZoneHorizontalPadding();
556     paintParameters.hotZoneVerticalPadding = checkBoxTheme->GetHotZoneVerticalPadding();
557     paintParameters.shadowWidth = checkBoxTheme->GetShadowWidth();
558     paintParameters.checkMarkPaintSize = checkBoxTheme->GetDefaultWidth().ConvertToPx();
559     paintParameters.hoverDuration = checkBoxTheme->GetHoverDuration();
560     paintParameters.hoverToTouchDuration = checkBoxTheme->GetHoverToTouchDuration();
561     paintParameters.uiStatus = UIStatus::UNSELECTED;
562     paintParameters.status = CheckBoxGroupPaintProperty::SelectStatus::NONE;
563     paintParameters.defaultPaddingSize = checkBoxTheme->GetDefaultPaddingSize();
564 }
565 
UpdateModifierParam(CheckBoxGroupModifier::Parameters & paintParameters)566 void CheckBoxGroupPattern::UpdateModifierParam(CheckBoxGroupModifier::Parameters& paintParameters)
567 {
568     auto host = GetHost();
569     CHECK_NULL_VOID(host);
570     auto paintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
571     CHECK_NULL_VOID(paintProperty);
572     auto geometryNode = host->GetGeometryNode();
573     CHECK_NULL_VOID(geometryNode);
574     auto contentSize = geometryNode->GetContentSize();
575 
576     if (paintProperty->HasCheckBoxGroupSelectedColor()) {
577         paintParameters.activeColor = paintProperty->GetCheckBoxGroupSelectedColorValue();
578     }
579     if (paintProperty->HasCheckBoxGroupUnSelectedColor()) {
580         paintParameters.inactiveColor = paintProperty->GetCheckBoxGroupUnSelectedColorValue();
581     }
582     if (paintProperty->HasCheckBoxGroupCheckMarkColor()) {
583         paintParameters.pointColor = paintProperty->GetCheckBoxGroupCheckMarkColorValue();
584     }
585     if (paintProperty->HasCheckBoxGroupCheckMarkSize()) {
586         if (paintProperty->GetCheckBoxGroupCheckMarkSizeValue().ConvertToPx() >= 0) {
587             paintParameters.checkMarkPaintSize = paintProperty->GetCheckBoxGroupCheckMarkSizeValue().ConvertToPx();
588         } else {
589             paintParameters.checkMarkPaintSize = contentSize.Width();
590         }
591     }
592     if (paintProperty->HasCheckBoxGroupCheckMarkWidth()) {
593         paintParameters.checkStroke =
594             static_cast<float>(paintProperty->GetCheckBoxGroupCheckMarkWidthValue().ConvertToPx());
595     }
596 }
597 
OnColorConfigurationUpdate()598 void CheckBoxGroupPattern::OnColorConfigurationUpdate()
599 {
600     auto host = GetHost();
601     CHECK_NULL_VOID(host);
602     auto pipeline = PipelineBase::GetCurrentContext();
603     CHECK_NULL_VOID(pipeline);
604     auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
605     CHECK_NULL_VOID(checkBoxTheme);
606     auto renderContext = host->GetRenderContext();
607     auto checkBoxGroupPaintProperty = host->GetPaintProperty<CheckBoxGroupPaintProperty>();
608     CHECK_NULL_VOID(checkBoxGroupPaintProperty);
609     checkBoxGroupPaintProperty->UpdateCheckBoxGroupSelectedColor(checkBoxTheme->GetActiveColor());
610     checkBoxGroupPaintProperty->UpdateCheckBoxGroupUnSelectedColor(checkBoxTheme->GetInactiveColor());
611     checkBoxGroupPaintProperty->UpdateCheckBoxGroupCheckMarkColor(checkBoxTheme->GetPointColor());
612     host->MarkModifyDone();
613     host->MarkDirtyNode();
614 }
615 
OnAttachToMainTree()616 void CheckBoxGroupPattern::OnAttachToMainTree()
617 {
618     auto host = GetHost();
619     CHECK_NULL_VOID(host);
620     auto groupManager = GetGroupManager();
621     CHECK_NULL_VOID(groupManager);
622     auto parent = host->GetParent();
623     while (parent) {
624         if (parent->GetTag() == V2::NAVDESTINATION_CONTENT_ETS_TAG) {
625             currentNavId_ = std::to_string(parent->GetId());
626             groupManager->SetLastNavId(currentNavId_);
627             UpdateState();
628             return;
629         }
630         parent = parent->GetParent();
631     }
632     if (!currentNavId_.value_or("").empty()) {
633         currentNavId_ = "";
634         groupManager->SetLastNavId(std::nullopt);
635         UpdateState();
636     }
637 }
638 
GetGroupNameWithNavId()639 std::string CheckBoxGroupPattern::GetGroupNameWithNavId()
640 {
641     auto host = GetHost();
642     CHECK_NULL_RETURN(host, "");
643     auto eventHub = host->GetEventHub<CheckBoxGroupEventHub>();
644     CHECK_NULL_RETURN(eventHub, "");
645     if (currentNavId_.has_value()) {
646         return eventHub->GetGroupName() + currentNavId_.value();
647     }
648     auto groupManager = GetGroupManager();
649     CHECK_NULL_RETURN(groupManager, eventHub->GetGroupName());
650     return eventHub->GetGroupName() + groupManager->GetLastNavId();
651 }
652 
GetGroupManager()653 RefPtr<GroupManager> CheckBoxGroupPattern::GetGroupManager()
654 {
655     auto manager = groupManager_.Upgrade();
656     if (manager) {
657         return manager;
658     }
659     groupManager_ = GroupManager::GetGroupManager();
660     return groupManager_.Upgrade();
661 }
662 
UpdateCheckBoxStyle()663 void CheckBoxGroupPattern::UpdateCheckBoxStyle()
664 {
665     auto host = GetHost();
666     CHECK_NULL_VOID(host);
667     auto groupManager = GetGroupManager();
668     CHECK_NULL_VOID(groupManager);
669     auto checkBoxGroupEventHub = GetEventHub<CheckBoxGroupEventHub>();
670     CHECK_NULL_VOID(checkBoxGroupEventHub);
671     auto group = checkBoxGroupEventHub->GetGroupName();
672     auto list = groupManager->GetCheckboxList(group);
673     CheckBoxStyle groupStyle;
674     GetCheckBoxGroupStyle(host, groupStyle);
675     for (auto node : list) {
676         if (!node) {
677             continue;
678         }
679         auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
680         CHECK_NULL_VOID(paintProperty);
681         SetCheckBoxStyle(paintProperty, node, groupStyle);
682     }
683     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
684 }
685 
GetCheckBoxGroupStyle(const RefPtr<FrameNode> & frameNode,CheckBoxStyle & checkboxGroupStyle)686 void CheckBoxGroupPattern::GetCheckBoxGroupStyle(const RefPtr<FrameNode>& frameNode, CheckBoxStyle& checkboxGroupStyle)
687 {
688     auto groupPaintProperty = frameNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
689     CHECK_NULL_VOID(groupPaintProperty);
690     checkboxGroupStyle = groupPaintProperty->GetCheckBoxGroupSelectedStyleValue(CheckBoxStyle::CIRCULAR_STYLE);
691 }
692 
SetCheckBoxStyle(const RefPtr<CheckBoxPaintProperty> & paintProperty,const RefPtr<FrameNode> & checkboxNode,CheckBoxStyle checkBoxGroupStyle)693 void CheckBoxGroupPattern::SetCheckBoxStyle(const RefPtr<CheckBoxPaintProperty>& paintProperty,
694     const RefPtr<FrameNode>& checkboxNode, CheckBoxStyle checkBoxGroupStyle)
695 {
696     CHECK_NULL_VOID(paintProperty);
697     CHECK_NULL_VOID(checkboxNode);
698     auto pattern = checkboxNode->GetPattern<CheckBoxPattern>();
699     CHECK_NULL_VOID(pattern);
700     if (!paintProperty->HasCheckBoxSelectedStyle() ||
701         pattern->GetOriginalCheckboxStyle() == OriginalCheckBoxStyle::NONE) {
702         pattern->SetOriginalCheckboxStyle(OriginalCheckBoxStyle::NONE);
703         paintProperty->UpdateCheckBoxSelectedStyle(checkBoxGroupStyle);
704         checkboxNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
705     }
706 }
707 } // namespace OHOS::Ace::NG
708