1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/checkbox/checkbox_pattern.h"
17
18 #include "core/components/checkable/checkable_component.h"
19 #include "core/components/checkable/checkable_theme.h"
20 #include "core/components_ng/pattern/checkbox/checkbox_layout_algorithm.h"
21 #include "core/components_ng/pattern/checkbox/checkbox_paint_property.h"
22 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_paint_property.h"
23 #include "core/components_ng/pattern/checkboxgroup/checkboxgroup_pattern.h"
24 #include "core/components_ng/pattern/stage/page_event_hub.h"
25 #include "core/components_ng/property/calc_length.h"
26 #include "core/components_ng/property/property.h"
27 #include "core/components_v2/inspector/inspector_constants.h"
28 #include "core/event/touch_event.h"
29 #include "core/pipeline/base/constants.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31
32 namespace OHOS::Ace::NG {
33
OnAttachToFrameNode()34 void CheckBoxPattern::OnAttachToFrameNode()
35 {
36 auto host = GetHost();
37 CHECK_NULL_VOID(host);
38 host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
39 }
40
OnModifyDone()41 void CheckBoxPattern::OnModifyDone()
42 {
43 Pattern::OnModifyDone();
44 UpdateState();
45 auto host = GetHost();
46 CHECK_NULL_VOID(host);
47 auto pipeline = PipelineBase::GetCurrentContext();
48 CHECK_NULL_VOID(pipeline);
49 auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
50 CHECK_NULL_VOID(checkBoxTheme);
51 auto layoutProperty = host->GetLayoutProperty();
52 CHECK_NULL_VOID(layoutProperty);
53 MarginProperty margin;
54 margin.left = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
55 margin.right = CalcLength(checkBoxTheme->GetHotZoneHorizontalPadding().Value());
56 margin.top = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
57 margin.bottom = CalcLength(checkBoxTheme->GetHotZoneVerticalPadding().Value());
58 auto& setMargin = layoutProperty->GetMarginProperty();
59 if (setMargin) {
60 if (setMargin->left.has_value()) {
61 margin.left = setMargin->left;
62 }
63 if (setMargin->right.has_value()) {
64 margin.right = setMargin->right;
65 }
66 if (setMargin->top.has_value()) {
67 margin.top = setMargin->top;
68 }
69 if (setMargin->bottom.has_value()) {
70 margin.bottom = setMargin->bottom;
71 }
72 }
73 layoutProperty->UpdateMargin(margin);
74 hotZoneHorizontalPadding_ = checkBoxTheme->GetHotZoneHorizontalPadding();
75 hotZoneVerticalPadding_ = checkBoxTheme->GetHotZoneVerticalPadding();
76 InitClickEvent();
77 InitTouchEvent();
78 InitMouseEvent();
79 auto focusHub = host->GetFocusHub();
80 CHECK_NULL_VOID(focusHub);
81 InitOnKeyEvent(focusHub);
82 }
83
InitClickEvent()84 void CheckBoxPattern::InitClickEvent()
85 {
86 if (clickListener_) {
87 return;
88 }
89 auto host = GetHost();
90 CHECK_NULL_VOID(host);
91 auto gesture = host->GetOrCreateGestureEventHub();
92 CHECK_NULL_VOID(gesture);
93 auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
94 auto checkboxPattern = weak.Upgrade();
95 CHECK_NULL_VOID(checkboxPattern);
96 checkboxPattern->OnClick();
97 };
98 clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
99 gesture->AddClickEvent(clickListener_);
100 }
101
InitTouchEvent()102 void CheckBoxPattern::InitTouchEvent()
103 {
104 if (touchListener_) {
105 return;
106 }
107 auto host = GetHost();
108 CHECK_NULL_VOID(host);
109 auto gesture = host->GetOrCreateGestureEventHub();
110 CHECK_NULL_VOID(gesture);
111 auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
112 auto checkboxPattern = weak.Upgrade();
113 CHECK_NULL_VOID(checkboxPattern);
114 if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
115 checkboxPattern->OnTouchDown();
116 }
117 if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
118 info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
119 checkboxPattern->OnTouchUp();
120 }
121 };
122 touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
123 gesture->AddTouchEvent(touchListener_);
124 }
125
InitMouseEvent()126 void CheckBoxPattern::InitMouseEvent()
127 {
128 if (mouseEvent_) {
129 return;
130 }
131 auto host = GetHost();
132 CHECK_NULL_VOID(host);
133 auto gesture = host->GetOrCreateGestureEventHub();
134 CHECK_NULL_VOID(gesture);
135 auto eventHub = host->GetEventHub<CheckBoxEventHub>();
136 auto inputHub = eventHub->GetOrCreateInputEventHub();
137
138 auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
139 auto pattern = weak.Upgrade();
140 if (pattern) {
141 pattern->HandleMouseEvent(isHover);
142 }
143 };
144 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
145 inputHub->AddOnHoverEvent(mouseEvent_);
146 }
147
HandleMouseEvent(bool isHover)148 void CheckBoxPattern::HandleMouseEvent(bool isHover)
149 {
150 isHover_ = isHover;
151 if (isHover) {
152 touchHoverType_ = TouchHoverAnimationType::HOVER;
153 } else {
154 touchHoverType_ = TouchHoverAnimationType::NONE;
155 }
156 auto host = GetHost();
157 CHECK_NULL_VOID(host);
158 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
159 }
160
OnClick()161 void CheckBoxPattern::OnClick()
162 {
163 auto host = GetHost();
164 CHECK_NULL_VOID(host);
165 auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
166 CHECK_NULL_VOID(paintProperty);
167 bool isSelected = false;
168 if (paintProperty->HasCheckBoxSelect()) {
169 isSelected = paintProperty->GetCheckBoxSelectValue();
170 } else {
171 isSelected = false;
172 }
173 paintProperty->UpdateCheckBoxSelect(!isSelected);
174 UpdateState();
175 }
176
OnTouchDown()177 void CheckBoxPattern::OnTouchDown()
178 {
179 if (isHover_) {
180 touchHoverType_ = TouchHoverAnimationType::HOVER_TO_PRESS;
181 } else {
182 touchHoverType_ = TouchHoverAnimationType::PRESS;
183 }
184 auto host = GetHost();
185 CHECK_NULL_VOID(host);
186 isTouch_ = true;
187 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
188 }
189
OnTouchUp()190 void CheckBoxPattern::OnTouchUp()
191 {
192 if (isHover_) {
193 touchHoverType_ = TouchHoverAnimationType::PRESS_TO_HOVER;
194 } else {
195 touchHoverType_ = TouchHoverAnimationType::NONE;
196 }
197 auto host = GetHost();
198 CHECK_NULL_VOID(host);
199 isTouch_ = false;
200 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
201 }
202
UpdateUnSelect()203 void CheckBoxPattern::UpdateUnSelect()
204 {
205 auto host = GetHost();
206 CHECK_NULL_VOID(host);
207 auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
208 CHECK_NULL_VOID(paintProperty);
209 if (paintProperty->HasCheckBoxSelect() && !paintProperty->GetCheckBoxSelectValue()) {
210 uiStatus_ = UIStatus::UNSELECTED;
211 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
212 }
213 }
214
UpdateUIStatus(bool check)215 void CheckBoxPattern::UpdateUIStatus(bool check)
216 {
217 uiStatus_ = check ? UIStatus::OFF_TO_ON : UIStatus::ON_TO_OFF;
218 auto host = GetHost();
219 CHECK_NULL_VOID(host);
220 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
221 }
222
OnDetachFromFrameNode(FrameNode * frameNode)223 void CheckBoxPattern::OnDetachFromFrameNode(FrameNode* frameNode)
224 {
225 CHECK_NULL_VOID(frameNode);
226 auto pipelineContext = PipelineContext::GetCurrentContext();
227 CHECK_NULL_VOID(pipelineContext);
228 auto stageManager = pipelineContext->GetStageManager();
229 CHECK_NULL_VOID(stageManager);
230 auto pageNode = stageManager->GetLastPage();
231 CHECK_NULL_VOID(pageNode);
232 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
233 CHECK_NULL_VOID(pageEventHub);
234 auto checkBoxEventHub = frameNode->GetEventHub<NG::CheckBoxEventHub>();
235 CHECK_NULL_VOID(checkBoxEventHub);
236 auto checkBoxGroupMap = pageEventHub->GetCheckBoxGroupMap();
237 UpdateCheckBoxGroupStatusWhenDetach(frameNode, checkBoxGroupMap);
238 pageEventHub->RemoveCheckBoxFromGroup(checkBoxEventHub->GetGroupName(), frameNode->GetId());
239 }
240
CheckPageNode()241 void CheckBoxPattern::CheckPageNode()
242 {
243 auto host = GetHost();
244 CHECK_NULL_VOID(host);
245 auto prePageId = GetPrePageId();
246 auto pipelineContext = PipelineContext::GetCurrentContext();
247 CHECK_NULL_VOID(pipelineContext);
248 auto stageManager = pipelineContext->GetStageManager();
249 CHECK_NULL_VOID(stageManager);
250 auto pageNode = stageManager->GetPageById(host->GetPageId());
251 CHECK_NULL_VOID_NOLOG(pageNode);
252 if (pageNode->GetId() != prePageId) {
253 auto eventHub = host->GetEventHub<CheckBoxEventHub>();
254 CHECK_NULL_VOID(eventHub);
255 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
256 CHECK_NULL_VOID(pageEventHub);
257 auto group = eventHub->GetGroupName();
258
259 pageEventHub->AddCheckBoxToGroup(group, host->GetId());
260 SetPrePageId(pageNode->GetId());
261 }
262 }
263
UpdateState()264 void CheckBoxPattern::UpdateState()
265 {
266 auto host = GetHost();
267 CHECK_NULL_VOID(host);
268 auto eventHub = host->GetEventHub<CheckBoxEventHub>();
269 CHECK_NULL_VOID(eventHub);
270 auto pipelineContext = PipelineContext::GetCurrentContext();
271 CHECK_NULL_VOID(pipelineContext);
272 auto stageManager = pipelineContext->GetStageManager();
273 CHECK_NULL_VOID(stageManager);
274 auto pageNode = stageManager->GetLastPage();
275 CHECK_NULL_VOID(pageNode);
276 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
277 CHECK_NULL_VOID(pageEventHub);
278 auto paintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
279 CHECK_NULL_VOID(paintProperty);
280 auto checkBoxGroupMap = pageEventHub->GetCheckBoxGroupMap();
281 auto preGroup = GetPreGroup();
282 auto group = eventHub->GetGroupName();
283 if (!preGroup.has_value()) {
284 pageEventHub->AddCheckBoxToGroup(group, host->GetId());
285 SetPrePageId(pageNode->GetId());
286 auto callback = [weak = WeakClaim(this)]() {
287 auto checkbox = weak.Upgrade();
288 if (checkbox) {
289 checkbox->CheckPageNode();
290 checkbox->CheckBoxGroupIsTrue();
291 }
292 };
293 pipelineContext->AddBuildFinishCallBack(callback);
294 if (paintProperty->HasCheckBoxSelect()) {
295 auto isSelected = paintProperty->GetCheckBoxSelectValue();
296 SetLastSelect(isSelected);
297 }
298 isFirstCreated_ = false;
299 SetPreGroup(group);
300 return;
301 }
302 if (preGroup.has_value() && preGroup.value() != group) {
303 pageEventHub->RemoveCheckBoxFromGroup(preGroup.value(), host->GetId());
304 pageEventHub->AddCheckBoxToGroup(group, host->GetId());
305 SetPrePageId(pageNode->GetId());
306 }
307 SetPreGroup(group);
308 bool isSelected = false;
309 if (paintProperty->HasCheckBoxSelect()) {
310 isSelected = paintProperty->GetCheckBoxSelectValue();
311 if (lastSelect_ != isSelected) {
312 UpdateUIStatus(isSelected);
313 SetLastSelect(isSelected);
314 auto checkboxEventHub = GetEventHub<CheckBoxEventHub>();
315 CHECK_NULL_VOID(checkboxEventHub);
316 checkboxEventHub->UpdateChangeEvent(isSelected);
317 }
318 }
319 UpdateCheckBoxGroupStatus(host, checkBoxGroupMap, isSelected);
320 }
321
UpdateCheckBoxGroupStatus(const RefPtr<FrameNode> & checkBoxFrameNode,std::unordered_map<std::string,std::list<WeakPtr<FrameNode>>> & checkBoxGroupMap,bool select)322 void CheckBoxPattern::UpdateCheckBoxGroupStatus(const RefPtr<FrameNode>& checkBoxFrameNode,
323 std::unordered_map<std::string, std::list<WeakPtr<FrameNode>>>& checkBoxGroupMap, bool select)
324 {
325 checkBoxFrameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
326 auto checkBoxEventHub = checkBoxFrameNode->GetEventHub<CheckBoxEventHub>();
327 CHECK_NULL_VOID(checkBoxEventHub);
328 auto group = checkBoxEventHub->GetGroupName();
329 std::vector<std::string> vec;
330 RefPtr<FrameNode> checkBoxGroupNode;
331 bool isSameAsSelf = true;
332 const auto& list = checkBoxGroupMap[group];
333 for (auto&& item : list) {
334 auto node = item.Upgrade();
335 if (!node) {
336 continue;
337 }
338 if (node == checkBoxFrameNode) {
339 if (select) {
340 auto eventHub = node->GetEventHub<CheckBoxEventHub>();
341 CHECK_NULL_VOID(eventHub);
342 vec.push_back(eventHub->GetName());
343 }
344 continue;
345 }
346 if (node->GetTag() == V2::CHECKBOXGROUP_ETS_TAG) {
347 checkBoxGroupNode = node;
348 continue;
349 }
350 auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
351 CHECK_NULL_VOID(paintProperty);
352 if (!paintProperty->HasCheckBoxSelect()) {
353 if (select) {
354 isSameAsSelf = false;
355 }
356 }
357 if (paintProperty->HasCheckBoxSelect() && paintProperty->GetCheckBoxSelectValue() != select) {
358 isSameAsSelf = false;
359 }
360 if (paintProperty->HasCheckBoxSelect() && paintProperty->GetCheckBoxSelectValue()) {
361 auto eventHub = node->GetEventHub<CheckBoxEventHub>();
362 CHECK_NULL_VOID(eventHub);
363 vec.push_back(eventHub->GetName());
364 }
365 }
366 CHECK_NULL_VOID(checkBoxGroupNode);
367 auto groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
368 CHECK_NULL_VOID(groupPaintProperty);
369 auto pattern = checkBoxGroupNode->GetPattern<CheckBoxGroupPattern>();
370 CHECK_NULL_VOID(pattern);
371 if (isSameAsSelf) {
372 if (select) {
373 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
374 pattern->UpdateUIStatus(select);
375 } else {
376 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
377 pattern->ResetUIStatus();
378 }
379 checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
380 } else {
381 auto checkBoxGroupStatus = groupPaintProperty->GetSelectStatus();
382 if (checkBoxGroupStatus == CheckBoxGroupPaintProperty::SelectStatus::ALL ||
383 checkBoxGroupStatus == CheckBoxGroupPaintProperty::SelectStatus::NONE) {
384 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::PART);
385 checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
386 }
387 }
388
389 auto status = groupPaintProperty->GetSelectStatus();
390 CheckboxGroupResult groupResult(vec, int(status));
391 auto eventHub = checkBoxGroupNode->GetEventHub<CheckBoxGroupEventHub>();
392 CHECK_NULL_VOID(eventHub);
393 eventHub->UpdateChangeEvent(&groupResult);
394 }
395
UpdateCheckBoxGroupStatusWhenDetach(const FrameNode * checkBoxFrameNode,std::unordered_map<std::string,std::list<WeakPtr<FrameNode>>> & checkBoxGroupMap)396 void CheckBoxPattern::UpdateCheckBoxGroupStatusWhenDetach(const FrameNode* checkBoxFrameNode,
397 std::unordered_map<std::string, std::list<WeakPtr<FrameNode>>>& checkBoxGroupMap)
398 {
399 auto checkBoxEventHub = checkBoxFrameNode->GetEventHub<CheckBoxEventHub>();
400 CHECK_NULL_VOID(checkBoxEventHub);
401 auto group = checkBoxEventHub->GetGroupName();
402 std::vector<std::string> vec;
403 RefPtr<FrameNode> checkBoxGroupNode;
404 bool haveCheckBoxSelected = false;
405 bool isAllCheckBoxSelected = true;
406 const auto& list = checkBoxGroupMap[group];
407 for (auto&& item : list) {
408 auto node = item.Upgrade();
409 if (!node) {
410 continue;
411 }
412 if (node->GetTag() == V2::CHECKBOXGROUP_ETS_TAG) {
413 checkBoxGroupNode = node;
414 continue;
415 }
416 auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
417 CHECK_NULL_VOID(paintProperty);
418 if (paintProperty->HasCheckBoxSelect() && paintProperty->GetCheckBoxSelectValue()) {
419 auto eventHub = node->GetEventHub<CheckBoxEventHub>();
420 CHECK_NULL_VOID(eventHub);
421 vec.push_back(eventHub->GetName());
422 haveCheckBoxSelected = true;
423 } else {
424 isAllCheckBoxSelected = false;
425 }
426 }
427 CHECK_NULL_VOID_NOLOG(checkBoxGroupNode);
428 auto groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
429 CHECK_NULL_VOID(groupPaintProperty);
430 auto pattern = checkBoxGroupNode->GetPattern<CheckBoxGroupPattern>();
431 CHECK_NULL_VOID(pattern);
432 if (haveCheckBoxSelected) {
433 if (isAllCheckBoxSelected) {
434 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
435 pattern->UpdateUIStatus(true);
436 } else {
437 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::PART);
438 pattern->ResetUIStatus();
439 }
440 } else {
441 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
442 pattern->UpdateUIStatus(false);
443 }
444 checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
445 auto status = groupPaintProperty->GetSelectStatus();
446 CheckboxGroupResult groupResult(vec, int(status));
447 auto eventHub = checkBoxGroupNode->GetEventHub<CheckBoxGroupEventHub>();
448 CHECK_NULL_VOID(eventHub);
449 eventHub->UpdateChangeEvent(&groupResult);
450 }
451
CheckBoxGroupIsTrue()452 void CheckBoxPattern::CheckBoxGroupIsTrue()
453 {
454 auto checkBoxFrameNode = GetHost();
455 CHECK_NULL_VOID(checkBoxFrameNode);
456 auto pipelineContext = PipelineContext::GetCurrentContext();
457 CHECK_NULL_VOID(pipelineContext);
458 auto stageManager = pipelineContext->GetStageManager();
459 CHECK_NULL_VOID(stageManager);
460 auto pageNode = stageManager->GetLastPage();
461 CHECK_NULL_VOID(pageNode);
462 auto pageEventHub = pageNode->GetEventHub<NG::PageEventHub>();
463 CHECK_NULL_VOID(pageEventHub);
464 auto paintProperty = checkBoxFrameNode->GetPaintProperty<CheckBoxPaintProperty>();
465 CHECK_NULL_VOID(paintProperty);
466 auto checkBoxGroupMap = pageEventHub->GetCheckBoxGroupMap();
467 auto checkBoxEventHub = checkBoxFrameNode->GetEventHub<CheckBoxEventHub>();
468 CHECK_NULL_VOID(checkBoxEventHub);
469 auto group = checkBoxEventHub->GetGroupName();
470 std::vector<std::string> vec;
471 RefPtr<FrameNode> checkBoxGroupNode;
472 bool allSelectIsNull = true;
473 const auto& list = checkBoxGroupMap[group];
474 for (auto&& item : list) {
475 auto node = item.Upgrade();
476 if (!node) {
477 continue;
478 }
479 if (node->GetTag() == V2::CHECKBOXGROUP_ETS_TAG) {
480 checkBoxGroupNode = node;
481 continue;
482 }
483 auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
484 CHECK_NULL_VOID(paintProperty);
485
486 if (paintProperty->HasCheckBoxSelect()) {
487 allSelectIsNull = false;
488 } else {
489 paintProperty->UpdateCheckBoxSelect(false);
490 }
491 }
492
493 CHECK_NULL_VOID_NOLOG(checkBoxGroupNode);
494 auto groupPaintProperty = checkBoxGroupNode->GetPaintProperty<CheckBoxGroupPaintProperty>();
495 if (groupPaintProperty->GetIsCheckBoxCallbackDealed()) {
496 return;
497 }
498 // All checkboxes do not set select status.
499 if (allSelectIsNull) {
500 if (groupPaintProperty->HasCheckBoxGroupSelect() && groupPaintProperty->GetCheckBoxGroupSelectValue()) {
501 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
502 groupPaintProperty->UpdateCheckBoxGroupSelect(true);
503 checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
504 for (auto&& item : list) {
505 auto node = item.Upgrade();
506 if (!node) {
507 continue;
508 }
509 if (node->GetTag() == V2::CHECKBOXGROUP_ETS_TAG) {
510 continue;
511 }
512 auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
513 CHECK_NULL_VOID(paintProperty);
514 paintProperty->UpdateCheckBoxSelect(true);
515 auto checkBoxPattern = node->GetPattern<CheckBoxPattern>();
516 CHECK_NULL_VOID(checkBoxPattern);
517 checkBoxPattern->UpdateUIStatus(true);
518 checkBoxPattern->SetLastSelect(true);
519 }
520 }
521 }
522 // Some checkboxes set select status.
523 if (!allSelectIsNull) {
524 bool allIsSame = true;
525 bool selfSelect = paintProperty->GetCheckBoxSelectValue();
526 for (auto&& item : list) {
527 auto node = item.Upgrade();
528 if (node == checkBoxFrameNode) {
529 continue;
530 }
531 if (!node) {
532 continue;
533 }
534 if (node->GetTag() == V2::CHECKBOXGROUP_ETS_TAG) {
535 continue;
536 }
537 auto paintProperty = node->GetPaintProperty<CheckBoxPaintProperty>();
538 CHECK_NULL_VOID(paintProperty);
539 if (selfSelect != paintProperty->GetCheckBoxSelectValue()) {
540 allIsSame = false;
541 }
542 node->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
543 }
544 auto checkBoxGroupPattern = checkBoxGroupNode->GetPattern<CheckBoxGroupPattern>();
545 CHECK_NULL_VOID(checkBoxGroupPattern);
546 if (allIsSame && paintProperty->GetCheckBoxSelectValue()) {
547 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::ALL);
548 checkBoxGroupPattern->UpdateUIStatus(true);
549 } else if (allIsSame && !paintProperty->GetCheckBoxSelectValue()) {
550 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::NONE);
551 checkBoxGroupPattern->ResetUIStatus();
552 } else {
553 groupPaintProperty->SetSelectStatus(CheckBoxGroupPaintProperty::SelectStatus::PART);
554 checkBoxGroupPattern->ResetUIStatus();
555 }
556 checkBoxGroupNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
557 }
558 groupPaintProperty->SetIsCheckBoxCallbackDealed(true);
559 }
560
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)561 void CheckBoxPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
562 {
563 auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
564 auto pattern = wp.Upgrade();
565 if (pattern) {
566 pattern->GetInnerFocusPaintRect(paintRect);
567 }
568 };
569 focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
570 }
571
GetInnerFocusPaintRect(RoundRect & paintRect)572 void CheckBoxPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
573 {
574 auto pipelineContext = PipelineBase::GetCurrentContext();
575 CHECK_NULL_VOID(pipelineContext);
576 auto checkBoxTheme = pipelineContext->GetTheme<CheckboxTheme>();
577 CHECK_NULL_VOID(checkBoxTheme);
578 auto borderRadius = checkBoxTheme->GetFocusRadius().ConvertToPx();
579 auto focusPaintPadding = checkBoxTheme->GetFocusPaintPadding().ConvertToPx();
580 float originX = offset_.GetX() - focusPaintPadding;
581 float originY = offset_.GetY() - focusPaintPadding;
582 float width = size_.Width() + 2 * focusPaintPadding;
583 float height = size_.Height() + 2 * focusPaintPadding;
584 paintRect.SetRect({ originX, originY, width, height });
585 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, borderRadius, borderRadius);
586 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, borderRadius, borderRadius);
587 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, borderRadius, borderRadius);
588 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, borderRadius, borderRadius);
589 }
590
GetFocusPattern() const591 FocusPattern CheckBoxPattern::GetFocusPattern() const
592 {
593 auto pipeline = PipelineBase::GetCurrentContext();
594 CHECK_NULL_RETURN(pipeline, FocusPattern());
595 auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
596 CHECK_NULL_RETURN(checkBoxTheme, FocusPattern());
597 auto activeColor = checkBoxTheme->GetActiveColor();
598 FocusPaintParam focusPaintParam;
599 focusPaintParam.SetPaintColor(activeColor);
600 return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParam };
601 }
602
603 // Set the default hot zone for the component.
AddHotZoneRect()604 void CheckBoxPattern::AddHotZoneRect()
605 {
606 hotZoneOffset_.SetX(offset_.GetX() - hotZoneHorizontalPadding_.ConvertToPx());
607 hotZoneOffset_.SetY(offset_.GetY() - hotZoneVerticalPadding_.ConvertToPx());
608 hotZoneSize_.SetWidth(size_.Width() + 2 * hotZoneHorizontalPadding_.ConvertToPx());
609 hotZoneSize_.SetHeight(size_.Height() + 2 * hotZoneVerticalPadding_.ConvertToPx());
610 DimensionRect hotZoneRegion;
611 hotZoneRegion.SetSize(DimensionSize(Dimension(hotZoneSize_.Width()), Dimension(hotZoneSize_.Height())));
612 hotZoneRegion.SetOffset(DimensionOffset(Dimension(hotZoneOffset_.GetX()), Dimension(hotZoneOffset_.GetY())));
613 auto host = GetHost();
614 CHECK_NULL_VOID(host);
615 auto gestureHub = host->GetOrCreateGestureEventHub();
616 CHECK_NULL_VOID(gestureHub);
617 std::vector<DimensionRect> hotZoneRegions;
618 hotZoneRegions.emplace_back(hotZoneRegion);
619 gestureHub->SetResponseRegion(hotZoneRegions);
620 }
621
RemoveLastHotZoneRect() const622 void CheckBoxPattern::RemoveLastHotZoneRect() const
623 {
624 auto host = GetHost();
625 CHECK_NULL_VOID(host);
626 host->RemoveLastHotZoneRect();
627 }
628
ProvideRestoreInfo()629 std::string CheckBoxPattern::ProvideRestoreInfo()
630 {
631 auto jsonObj = JsonUtil::Create(true);
632 auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
633 CHECK_NULL_RETURN(checkBoxPaintProperty, "");
634 jsonObj->Put("isOn", checkBoxPaintProperty->GetCheckBoxSelect().value_or(false));
635 return jsonObj->ToString();
636 }
637
OnRestoreInfo(const std::string & restoreInfo)638 void CheckBoxPattern::OnRestoreInfo(const std::string& restoreInfo)
639 {
640 auto checkBoxPaintProperty = GetPaintProperty<CheckBoxPaintProperty>();
641 CHECK_NULL_VOID(checkBoxPaintProperty);
642 auto info = JsonUtil::ParseJsonString(restoreInfo);
643 if (!info->IsValid() || !info->IsObject()) {
644 return;
645 }
646 auto jsonCheckBoxSelect = info->GetValue("isOn");
647 checkBoxPaintProperty->UpdateCheckBoxSelect(jsonCheckBoxSelect->GetBool());
648 }
649
OnColorConfigurationUpdate()650 void CheckBoxPattern::OnColorConfigurationUpdate()
651 {
652 auto host = GetHost();
653 CHECK_NULL_VOID(host);
654 auto pipeline = PipelineBase::GetCurrentContext();
655 CHECK_NULL_VOID(pipeline);
656 auto checkBoxTheme = pipeline->GetTheme<CheckboxTheme>();
657 CHECK_NULL_VOID(checkBoxTheme);
658 auto checkBoxPaintProperty = host->GetPaintProperty<CheckBoxPaintProperty>();
659 CHECK_NULL_VOID(checkBoxPaintProperty);
660 checkBoxPaintProperty->UpdateCheckBoxSelectedColor(checkBoxTheme->GetActiveColor());
661 checkBoxPaintProperty->UpdateCheckBoxUnSelectedColor(checkBoxTheme->GetInactiveColor());
662 checkBoxPaintProperty->UpdateCheckBoxCheckMarkColor(checkBoxTheme->GetPointColor());
663 host->MarkModifyDone();
664 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
665 }
666
667 } // namespace OHOS::Ace::NG
668