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