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