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/i18n/localization.h"
17 #include "core/components_ng/pattern/patternlock/patternlock_pattern.h"
18
19 #include "core/components_ng/pattern/patternlock/patternlock_paint_property.h"
20 #include "core/components_ng/pattern/stage/page_event_hub.h"
21 #include "core/components_ng/pattern/text/text_pattern.h"
22 #include "core/components_ng/property/calc_length.h"
23 #include "core/components_ng/property/property.h"
24 #include "core/components_v2/inspector/inspector_constants.h"
25 #include "core/components_v2/pattern_lock/pattern_lock_component.h"
26 #include "core/event/touch_event.h"
27 #include "core/pipeline/base/constants.h"
28 #include "core/pipeline_ng/pipeline_context.h"
29
30 namespace OHOS::Ace::NG {
31 namespace {
32 constexpr int32_t PATTERN_LOCK_COL_COUNT = 3;
33 constexpr int32_t RADIUS_TO_DIAMETER = 2;
34 constexpr int32_t RADIUS_COUNT = 6;
35 } // namespace
36
OnAttachToFrameNode()37 void PatternLockPattern::OnAttachToFrameNode()
38 {
39 auto host = GetHost();
40 CHECK_NULL_VOID(host);
41 host->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
42 }
43
OnModifyDone()44 void PatternLockPattern::OnModifyDone()
45 {
46 Pattern::OnModifyDone();
47 auto host = GetHost();
48 CHECK_NULL_VOID(host);
49
50 auto gestureHub = host->GetOrCreateGestureEventHub();
51 InitTouchEvent(gestureHub, touchDownListener_);
52 InitPatternLockController();
53 InitFocusEvent();
54 InitMouseEvent();
55 InitAccessibilityHoverEvent();
56 if (isInitVirtualNode_) {
57 auto pipeline = host->GetContext();
58 CHECK_NULL_VOID(pipeline);
59 pipeline->AddAfterRenderTask([weak = WeakClaim(this)]() {
60 auto patternLock = weak.Upgrade();
61 CHECK_NULL_VOID(patternLock);
62 patternLock->ModifyAccessibilityVirtualNode();
63 });
64 }
65 }
66
InitTouchEvent(RefPtr<GestureEventHub> & gestureHub,RefPtr<TouchEventImpl> & touchDownListener)67 void PatternLockPattern::InitTouchEvent(RefPtr<GestureEventHub>& gestureHub, RefPtr<TouchEventImpl>& touchDownListener)
68 {
69 if (touchDownListener) {
70 return;
71 }
72 auto touchDownTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
73 auto pattern = weak.Upgrade();
74 CHECK_NULL_VOID(pattern);
75 pattern->HandleTouchEvent(info);
76 };
77 touchDownListener = MakeRefPtr<TouchEventImpl>(std::move(touchDownTask));
78 gestureHub->AddTouchEvent(touchDownListener);
79 gestureHub->SetHitTestMode(HitTestMode::HTMBLOCK);
80 }
81
SetChallengeResult(V2::PatternLockChallengeResult challengeResult)82 void PatternLockPattern::SetChallengeResult(V2::PatternLockChallengeResult challengeResult)
83 {
84 if (!isMoveEventValid_) {
85 CHECK_NULL_VOID(patternLockModifier_);
86 std::optional<NG::PatternLockChallengeResult> ngChallengeResult;
87 if (challengeResult == V2::PatternLockChallengeResult::CORRECT) {
88 ngChallengeResult = NG::PatternLockChallengeResult::CORRECT;
89 } else if (challengeResult == V2::PatternLockChallengeResult::WRONG) {
90 ngChallengeResult = NG::PatternLockChallengeResult::WRONG;
91 }
92 patternLockModifier_->SetChallengeResult(ngChallengeResult);
93 }
94 }
95
InitPatternLockController()96 void PatternLockPattern::InitPatternLockController()
97 {
98 patternLockController_->SetResetImpl([weak = WeakClaim(this)]() {
99 auto patternLock = weak.Upgrade();
100 CHECK_NULL_VOID(patternLock);
101 patternLock->HandleReset();
102 });
103 patternLockController_->SetChallengeResultImpl(
104 [weak = WeakClaim(this)](V2::PatternLockChallengeResult challengeResult) {
105 auto patternLock = weak.Upgrade();
106 CHECK_NULL_VOID(patternLock);
107 patternLock->SetChallengeResult(challengeResult);
108 });
109 }
110
InitAccessibilityHoverEvent()111 void PatternLockPattern::InitAccessibilityHoverEvent()
112 {
113 auto host = GetHost();
114 CHECK_NULL_VOID(host);
115 auto eventHub = host->GetOrCreateInputEventHub();
116 eventHub->SetAccessibilityHoverEvent([weak = WeakClaim(this)](bool isHover, AccessibilityHoverInfo& info) {
117 auto patternLock = weak.Upgrade();
118 CHECK_NULL_VOID(patternLock);
119 patternLock->HandleAccessibilityHoverEvent(isHover, info);
120 });
121 }
122
HandleAccessibilityHoverEvent(bool isHover,AccessibilityHoverInfo & info)123 void PatternLockPattern::HandleAccessibilityHoverEvent(bool isHover, AccessibilityHoverInfo& info)
124 {
125 auto accessibilityHoverAction = info.GetActionType();
126 if (isHover && (accessibilityHoverAction == AccessibilityHoverAction::HOVER_ENTER ||
127 accessibilityHoverAction == AccessibilityHoverAction::HOVER_MOVE)) {
128 for (const auto& accessibilityProperty : accessibilityPropertyVec_) {
129 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::YES_STR);
130 }
131 if (!CheckAutoReset()) {
132 return;
133 }
134 HandleReset();
135 } else if (!isHover) {
136 for (const auto& accessibilityProperty : accessibilityPropertyVec_) {
137 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
138 }
139 AddPointEnd();
140 auto host = GetHost();
141 auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
142 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::YES_STR);
143 }
144 }
145
InitVirtualNode()146 bool PatternLockPattern::InitVirtualNode()
147 {
148 auto host = GetHost();
149 CHECK_NULL_RETURN(host, false);
150 float handleCircleRadius = 0.0f;
151 if (!GetHandleCircleRadius(handleCircleRadius)) {
152 return false;
153 }
154 auto lineNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
155 AceType::MakeRefPtr<LinearLayoutPattern>(true));
156 auto renderContext = lineNode->GetRenderContext();
157 CHECK_NULL_RETURN(renderContext, false);
158 renderContext->UpdatePosition(OffsetT(Dimension(0.0f), Dimension(0.0f)));
159 for (int32_t y = 0; y < PATTERN_LOCK_COL_COUNT; y++) {
160 for (int32_t x = 0; x < PATTERN_LOCK_COL_COUNT; x++) {
161 auto textNode = AddTextNodeIntoVirtual(x + 1, y + 1, handleCircleRadius);
162 lineNode->AddChild(textNode);
163 textAccessibilityNodeVec_.emplace_back(textNode);
164 }
165 }
166 auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
167 accessibilityProperty->SetAccessibilityText(" ");
168 auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(lineNode);
169 CHECK_NULL_RETURN(virtualFrameNode, false);
170 virtualFrameNode->SetAccessibilityNodeVirtual();
171 virtualFrameNode->SetAccessibilityVirtualNodeParent(AceType::DynamicCast<NG::UINode>(host));
172 virtualFrameNode->SetFirstAccessibilityVirtualNode();
173 FrameNode::ProcessOffscreenNode(virtualFrameNode);
174 accessibilityProperty->SaveAccessibilityVirtualNode(lineNode);
175 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
176 ModifyAccessibilityVirtualNode();
177 return true;
178 }
179
AddTextNodeIntoVirtual(int32_t x,int32_t y,float handleCircleRadius)180 RefPtr<FrameNode> PatternLockPattern::AddTextNodeIntoVirtual(int32_t x, int32_t y, float handleCircleRadius)
181 {
182 auto textNode = FrameNode::CreateFrameNode(
183 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
184 UpdateAccessibilityTextNode(textNode, handleCircleRadius, x, y);
185 auto textAccessibilityProperty = textNode->GetAccessibilityProperty<AccessibilityProperty>();
186 accessibilityPropertyVec_.emplace_back(textAccessibilityProperty);
187 textAccessibilityProperty->SetOnAccessibilityFocusCallback([weak = WeakClaim(this), x, y](bool focus) {
188 if (focus) {
189 auto patternLock = weak.Upgrade();
190 CHECK_NULL_VOID(patternLock);
191 patternLock->HandleTextOnAccessibilityFocusCallback(x, y);
192 }
193 });
194 return textNode;
195 }
196
197
HandleTextOnAccessibilityFocusCallback(int32_t x,int32_t y)198 void PatternLockPattern::HandleTextOnAccessibilityFocusCallback(int32_t x, int32_t y)
199 {
200 if (!CheckChoosePoint(x, y)) {
201 AddPassPoint(x, y);
202 choosePoint_.emplace_back(x, y);
203 StartModifierConnectedAnimate(x, y);
204 auto host = GetHost();
205 auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
206 accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
207 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
208 }
209 }
210
211
ModifyAccessibilityVirtualNode()212 void PatternLockPattern::ModifyAccessibilityVirtualNode()
213 {
214 if (textAccessibilityNodeVec_.size() < 1) {
215 return;
216 }
217 float handleCircleRadius = 0.0f;
218 if (!GetHandleCircleRadius(handleCircleRadius)) {
219 return;
220 }
221 for (int32_t y = 0; y < PATTERN_LOCK_COL_COUNT; y++) {
222 for (int32_t x = 0; x < PATTERN_LOCK_COL_COUNT; x++) {
223 auto textNode = textAccessibilityNodeVec_[y * PATTERN_LOCK_COL_COUNT + x];
224 UpdateAccessibilityTextNode(textNode, handleCircleRadius, x, y);
225 }
226 }
227 auto host = GetHost();
228 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
229 }
230
ReplacePlaceHolder(const std::string & str,int32_t number)231 std::string PatternLockPattern::ReplacePlaceHolder(const std::string& str, int32_t number)
232 {
233 std::string result = str;
234 std::string numberStr = std::to_string(number);
235
236 size_t pos = result.find("%d");
237 if (pos != std::string::npos) {
238 result.replace(pos, 2, numberStr); // 2: "%d" length
239 } else {
240 result = str + numberStr;
241 }
242
243 return result;
244 }
245
UpdateAccessibilityTextNode(RefPtr<FrameNode> frameNode,float handleCircleRadius,int32_t x,int32_t y)246 void PatternLockPattern::UpdateAccessibilityTextNode(
247 RefPtr<FrameNode> frameNode, float handleCircleRadius, int32_t x, int32_t y)
248 {
249 auto host = GetHost();
250 CHECK_NULL_VOID(host);
251 OffsetF contentOffset = host->GetGeometryNode()->GetContentOffset();
252 float sideLength = host->GetGeometryNode()->GetContentSize().Width();
253 int32_t scale = RADIUS_TO_DIAMETER;
254 float offsetX = sideLength / PATTERN_LOCK_COL_COUNT / scale * (scale * (x + 1) - 1);
255 float offsetY = sideLength / PATTERN_LOCK_COL_COUNT / scale * (scale * (y + 1) - 1);
256 int32_t index = y * PATTERN_LOCK_COL_COUNT + x + 1;
257 auto pipeline = host->GetContext();
258 CHECK_NULL_VOID(pipeline);
259 auto patternLockTheme = pipeline->GetTheme<V2::PatternLockTheme>();
260 CHECK_NULL_VOID(patternLockTheme);
261 auto message = patternLockTheme->GetPassPointTxt();
262 std::string text = ReplacePlaceHolder(message, index);
263 CHECK_NULL_VOID(frameNode);
264 auto textLayoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
265 CHECK_NULL_VOID(textLayoutProperty);
266 textLayoutProperty->UpdateContent(text);
267 Dimension focusPaddingRadius = Dimension(handleCircleRadius * RADIUS_TO_DIAMETER);
268 CalcLength width = CalcLength(focusPaddingRadius);
269 CalcLength height = CalcLength(focusPaddingRadius);
270 textLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, height));
271 auto renderContext = frameNode->GetRenderContext();
272 CHECK_NULL_VOID(renderContext);
273 Dimension textOffsetX = Dimension(offsetX - handleCircleRadius + contentOffset.GetX());
274 Dimension textOffsetY = Dimension(offsetY - handleCircleRadius + contentOffset.GetY());
275 renderContext->UpdatePosition(OffsetT(textOffsetX, textOffsetY));
276 frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
277 }
278
HandleTouchEvent(const TouchEventInfo & info)279 void PatternLockPattern::HandleTouchEvent(const TouchEventInfo& info)
280 {
281 auto touchList = info.GetChangedTouches();
282 CHECK_NULL_VOID(!touchList.empty());
283 if (fingerId_ == -1) {
284 fingerId_ = touchList.front().GetFingerId();
285 }
286 for (const auto& touchInfo : touchList) {
287 if (touchInfo.GetFingerId() == fingerId_) {
288 auto touchType = touchInfo.GetTouchType();
289 if (touchType == TouchType::DOWN) {
290 OnTouchDown(touchInfo);
291 } else if (touchType == TouchType::MOVE) {
292 OnTouchMove(touchInfo);
293 } else if (touchType == TouchType::UP) {
294 OnTouchUp();
295 }
296 break;
297 }
298 }
299 }
300
GetHandleCircleRadius(float & handleCircleRadius)301 bool PatternLockPattern::GetHandleCircleRadius(float& handleCircleRadius)
302 {
303 auto host = GetHost();
304 CHECK_NULL_RETURN(host, false);
305 auto patternLockPaintProperty = host->GetPaintProperty<PatternLockPaintProperty>();
306 float sideLength = host->GetGeometryNode()->GetContentSize().Width();
307 auto pipelineContext = PipelineBase::GetCurrentContext();
308 CHECK_NULL_RETURN(pipelineContext, false);
309 auto patternLockTheme = pipelineContext->GetTheme<V2::PatternLockTheme>();
310 CHECK_NULL_RETURN(patternLockTheme, false);
311 circleRadius_ = patternLockTheme->GetCircleRadius();
312 if (patternLockPaintProperty->HasCircleRadius()) {
313 circleRadius_ = patternLockPaintProperty->GetCircleRadiusValue();
314 }
315 auto backgroundRadiusScale = patternLockTheme->GetBackgroundRadiusScale();
316 if (NearZero(backgroundRadiusScale)) {
317 return false;
318 }
319 auto activeCircleRadiusScale = patternLockTheme->GetActiveCircleRadiusScale();
320 handleCircleRadius = std::min(static_cast<float>(circleRadius_.ConvertToPxWithSize(sideLength)),
321 sideLength / backgroundRadiusScale / RADIUS_COUNT);
322 auto hotSpotCircleRadius = patternLockTheme->GetHotSpotCircleRadius();
323 handleCircleRadius = std::max(handleCircleRadius * activeCircleRadiusScale,
324 std::min(
325 static_cast<float>(hotSpotCircleRadius.ConvertToPx()) / RADIUS_TO_DIAMETER, sideLength / RADIUS_COUNT));
326 return true;
327 }
328
329
CheckInHotSpot(const OffsetF & offset,int32_t x,int32_t y)330 bool PatternLockPattern::CheckInHotSpot(const OffsetF& offset, int32_t x, int32_t y)
331 {
332 auto host = GetHost();
333 CHECK_NULL_RETURN(host, false);
334 float sideLength = host->GetGeometryNode()->GetContentSize().Width();
335 OffsetF contentOffset = host->GetGeometryNode()->GetContentOffset();
336 auto handleCircleRadius = 0.0f;
337 if (!GetHandleCircleRadius(handleCircleRadius)) {
338 return false;
339 }
340 const int32_t scale = RADIUS_TO_DIAMETER;
341 float offsetX = sideLength / PATTERN_LOCK_COL_COUNT / scale * (scale * x - 1);
342 float offsetY = sideLength / PATTERN_LOCK_COL_COUNT / scale * (scale * y - 1);
343 offsetX += contentOffset.GetX();
344 offsetY += contentOffset.GetY();
345 OffsetF centerOffset;
346 centerOffset.SetX(offsetX);
347 centerOffset.SetY(offsetY);
348 auto X = (offset - centerOffset).GetX();
349 auto Y = (offset - centerOffset).GetY();
350 float distance = std::sqrt((X * X) + (Y * Y));
351 return LessOrEqual(distance, handleCircleRadius);
352 }
353
AddChoosePoint(const OffsetF & offset,int32_t x,int32_t y)354 bool PatternLockPattern::AddChoosePoint(const OffsetF& offset, int32_t x, int32_t y)
355 {
356 if (CheckInHotSpot(offset, x, y)) {
357 if (!CheckChoosePoint(x, y)) {
358 AddPassPoint(x, y);
359 choosePoint_.emplace_back(x, y);
360 StartModifierConnectedAnimate(x, y);
361 UpdateDotConnectEvent();
362 }
363 return true;
364 }
365 return false;
366 }
367
CheckChoosePoint(int32_t x,int32_t y) const368 bool PatternLockPattern::CheckChoosePoint(int32_t x, int32_t y) const
369 {
370 for (auto it : choosePoint_) {
371 if (it.GetColumn() == x && it.GetRow() == y) {
372 return true;
373 }
374 }
375 return false;
376 }
377
UpdateDotConnectEvent()378 void PatternLockPattern::UpdateDotConnectEvent()
379 {
380 auto host = GetHost();
381 CHECK_NULL_VOID(host);
382 auto eventHub = host->GetEventHub<PatternLockEventHub>();
383 CHECK_NULL_VOID(eventHub);
384 eventHub->UpdateDotConnectEvent(choosePoint_.back().GetCode());
385 }
386
AddPassPointToChoosePoint(int32_t lastCode,int32_t nowCode,std::vector<PatternLockCell> passPointVec)387 void PatternLockPattern::AddPassPointToChoosePoint(
388 int32_t lastCode, int32_t nowCode, std::vector<PatternLockCell> passPointVec)
389 {
390 passPointCount_ = static_cast<int32_t>(passPointVec.size());
391 if (nowCode > lastCode) {
392 choosePoint_.emplace_back(passPointVec.front());
393 UpdateDotConnectEvent();
394 StartModifierAddPassPointAnimate(passPointVec.front().GetColumn(), passPointVec.front().GetRow());
395 if (passPointCount_ > 1) {
396 choosePoint_.emplace_back(passPointVec.back());
397 UpdateDotConnectEvent();
398 StartModifierAddPassPointAnimate(passPointVec.back().GetColumn(), passPointVec.back().GetRow());
399 }
400 } else {
401 choosePoint_.emplace_back(passPointVec.back());
402 UpdateDotConnectEvent();
403 StartModifierAddPassPointAnimate(passPointVec.back().GetColumn(), passPointVec.back().GetRow());
404 if (passPointCount_ > 1) {
405 choosePoint_.emplace_back(passPointVec.front());
406 UpdateDotConnectEvent();
407 StartModifierAddPassPointAnimate(passPointVec.front().GetColumn(), passPointVec.front().GetRow());
408 }
409 }
410 }
411
AddPassPoint(int32_t x,int32_t y)412 void PatternLockPattern::AddPassPoint(int32_t x, int32_t y)
413 {
414 if (choosePoint_.empty()) {
415 return;
416 }
417 passPointCount_ = 0;
418 PatternLockCell lastCell = choosePoint_.back();
419 int32_t lastX = lastCell.GetColumn();
420 int32_t lastY = lastCell.GetRow();
421 int32_t lastCode = lastCell.GetCode();
422 int32_t nowCode = PATTERN_LOCK_COL_COUNT * (y - 1) + (x - 1);
423 std::vector<PatternLockCell> passPointVec;
424 for (int32_t i = 1; i <= PATTERN_LOCK_COL_COUNT; i++) {
425 for (int32_t j = 1; j <= PATTERN_LOCK_COL_COUNT; j++) {
426 PatternLockCell passPoint = PatternLockCell(i, j);
427 if ((passPoint.GetCode() >= nowCode && passPoint.GetCode() >= lastCode) ||
428 (passPoint.GetCode() <= nowCode && passPoint.GetCode() <= lastCode)) {
429 continue;
430 }
431 if ((j != y) && (j != lastY) &&
432 (NearEqual(static_cast<float>(lastX - i) / (lastY - j), static_cast<float>(i - x) / (j - y)) &&
433 !CheckChoosePoint(i, j))) {
434 passPointVec.emplace_back(passPoint);
435 }
436 if ((j == lastY) && (j == y) && !CheckChoosePoint(i, j)) {
437 passPointVec.emplace_back(passPoint);
438 }
439 }
440 }
441 size_t passPointLength = passPointVec.size();
442 if (passPointLength == 0) {
443 return;
444 }
445 AddPassPointToChoosePoint(lastCode, nowCode, passPointVec);
446 }
447
HandleReset()448 void PatternLockPattern::HandleReset()
449 {
450 isMoveEventValid_ = false;
451 isOnKeyEventState_ = false;
452 choosePoint_.clear();
453 cellCenter_.Reset();
454 if (patternLockModifier_) {
455 patternLockModifier_->Reset();
456 }
457 auto host = GetHost();
458 CHECK_NULL_VOID(host);
459 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
460 }
461
CheckAutoReset() const462 bool PatternLockPattern::CheckAutoReset() const
463 {
464 auto host = GetHost();
465 CHECK_NULL_RETURN(host, false);
466 auto patternLockPaintProperty = host->GetPaintProperty<PatternLockPaintProperty>();
467 if (patternLockPaintProperty->HasAutoReset()) {
468 autoReset_ = patternLockPaintProperty->GetAutoResetValue();
469 }
470 return !(!autoReset_ && !choosePoint_.empty() && !isMoveEventValid_);
471 }
472
OnTouchDown(const TouchLocationInfo & info)473 void PatternLockPattern::OnTouchDown(const TouchLocationInfo& info)
474 {
475 auto locationX = static_cast<float>(info.GetLocalLocation().GetX());
476 auto locationY = static_cast<float>(info.GetLocalLocation().GetY());
477 screenTouchPoint_.SetX(locationX);
478 screenTouchPoint_.SetY(locationY);
479
480 if (!CheckAutoReset()) {
481 return;
482 }
483 HandleReset();
484 CalculateCellCenter();
485 bool isAdd = false;
486 for (int32_t i = 0; i < PATTERN_LOCK_COL_COUNT && !isAdd; i++) {
487 for (int32_t j = 0; j < PATTERN_LOCK_COL_COUNT && !isAdd; j++) {
488 isAdd = AddChoosePoint(cellCenter_, i + 1, j + 1);
489 }
490 }
491
492 if (patternLockModifier_) {
493 patternLockModifier_->SetIsTouchDown(true);
494 }
495 auto host = GetHost();
496 CHECK_NULL_VOID(host);
497 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
498 isMoveEventValid_ = true;
499 }
500
OnTouchMove(const TouchLocationInfo & info)501 void PatternLockPattern::OnTouchMove(const TouchLocationInfo& info)
502 {
503 auto locationX = static_cast<float>(info.GetLocalLocation().GetX());
504 auto locationY = static_cast<float>(info.GetLocalLocation().GetY());
505 screenTouchPoint_.SetX(locationX);
506 screenTouchPoint_.SetY(locationY);
507 if (!isMoveEventValid_) {
508 return;
509 }
510 CalculateCellCenter();
511 bool isAdd = false;
512 for (int32_t i = 0; i < PATTERN_LOCK_COL_COUNT && !isAdd; i++) {
513 for (int32_t j = 0; j < PATTERN_LOCK_COL_COUNT && !isAdd; j++) {
514 isAdd = AddChoosePoint(cellCenter_, i + 1, j + 1);
515 }
516 }
517
518 auto host = GetHost();
519 CHECK_NULL_VOID(host);
520 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
521 }
522
AddPointEnd()523 void PatternLockPattern::AddPointEnd()
524 {
525 if (!CheckAutoReset()) {
526 return;
527 }
528 isMoveEventValid_ = false;
529 std::vector<int> chooseCellVec;
530 for (auto& it : choosePoint_) {
531 chooseCellVec.emplace_back(it.GetCode());
532 }
533 auto host = GetHost();
534 CHECK_NULL_VOID(host);
535 auto eventHub = host->GetEventHub<PatternLockEventHub>();
536 CHECK_NULL_VOID(eventHub);
537
538 auto patternCompleteEvent = V2::PatternCompleteEvent(chooseCellVec);
539 eventHub->UpdateCompleteEvent(&patternCompleteEvent);
540 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
541 }
542
OnTouchUp()543 void PatternLockPattern::OnTouchUp()
544 {
545 CHECK_NULL_VOID(patternLockModifier_);
546 patternLockModifier_->SetIsTouchDown(false);
547 size_t count = patternLockModifier_->GetChoosePointCount();
548 if (count < 1) {
549 return;
550 }
551 StartModifierCanceledAnimate();
552 AddPointEnd();
553 fingerId_ = -1;
554 }
555
InitFocusEvent()556 void PatternLockPattern::InitFocusEvent()
557 {
558 auto host = GetHost();
559 CHECK_NULL_VOID(host);
560 auto focusHub = host->GetOrCreateFocusHub();
561 CHECK_NULL_VOID(focusHub);
562
563 auto focusTask = [weak = WeakClaim(this)]() {
564 auto pattern = weak.Upgrade();
565 CHECK_NULL_VOID(pattern);
566 pattern->HandleFocusEvent();
567 };
568 focusHub->SetOnFocusInternal(focusTask);
569 auto blurTask = [weak = WeakClaim(this)]() {
570 auto pattern = weak.Upgrade();
571 CHECK_NULL_VOID(pattern);
572 pattern->HandleBlurEvent();
573 };
574 focusHub->SetOnBlurInternal(blurTask);
575 auto keyTask = [weak = WeakClaim(this)](const KeyEvent& keyEvent) -> bool {
576 auto pattern = weak.Upgrade();
577 CHECK_NULL_RETURN(pattern, false);
578 return pattern->OnKeyEvent(keyEvent);
579 };
580 focusHub->SetOnKeyEventInternal(keyTask);
581 auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
582 auto pattern = wp.Upgrade();
583 CHECK_NULL_VOID(pattern);
584 pattern->GetInnerFocusPaintRect(paintRect);
585 };
586 focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
587 }
588
HandleFocusEvent()589 void PatternLockPattern::HandleFocusEvent()
590 {
591 HandleReset();
592 currentPoint_ = { 1, 1 };
593 isMoveEventValid_ = true;
594 }
595
HandleBlurEvent()596 void PatternLockPattern::HandleBlurEvent()
597 {
598 isMoveEventValid_ = false;
599 }
600
GetInnerFocusPaintRect(RoundRect & paintRect)601 void PatternLockPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
602 {
603 auto host = GetHost();
604 CHECK_NULL_VOID(host);
605 auto pipelineContext = PipelineBase::GetCurrentContext();
606 CHECK_NULL_VOID(pipelineContext);
607 auto patternLockTheme = pipelineContext->GetTheme<V2::PatternLockTheme>();
608 CHECK_NULL_VOID(patternLockTheme);
609 auto patternLockPaintProperty = host->GetPaintProperty<PatternLockPaintProperty>();
610 CHECK_NULL_VOID(patternLockPaintProperty);
611 auto geometryNode = host->GetGeometryNode();
612 CHECK_NULL_VOID(geometryNode);
613 OffsetF contentOffset = geometryNode->GetContentOffset();
614 float sideLength = geometryNode->GetContentSize().Width();
615 float offset = sideLength / PATTERN_LOCK_COL_COUNT;
616 float circleRadius = patternLockPaintProperty->GetCircleRadius()
617 .value_or(patternLockTheme->GetCircleRadius())
618 .ConvertToPxWithSize(sideLength);
619 auto backgroundRadiusScale = patternLockTheme->GetBackgroundRadiusScale();
620 auto focusPaddingRadius = patternLockTheme->GetFocusPaddingRadius();
621 auto focusPaintWidth = patternLockTheme->GetFocusPaintWidth();
622 float foucusCircleRadius = std::min(circleRadius * backgroundRadiusScale, offset / RADIUS_TO_DIAMETER) +
623 (focusPaddingRadius).ConvertToPx() + focusPaintWidth.ConvertToPx() / RADIUS_TO_DIAMETER;
624 float outRadius = offset / RADIUS_TO_DIAMETER - foucusCircleRadius;
625 float offsetX = contentOffset.GetX() + (currentPoint_.first - 1) * offset + outRadius;
626 float offsetY = contentOffset.GetY() + (currentPoint_.second - 1) * offset + outRadius;
627
628 paintRect.SetRect(
629 { offsetX, offsetY, foucusCircleRadius * RADIUS_TO_DIAMETER, foucusCircleRadius * RADIUS_TO_DIAMETER });
630 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, foucusCircleRadius, foucusCircleRadius);
631 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, foucusCircleRadius, foucusCircleRadius);
632 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, foucusCircleRadius, foucusCircleRadius);
633 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, foucusCircleRadius, foucusCircleRadius);
634 }
635
OnFocusClick()636 void PatternLockPattern::OnFocusClick()
637 {
638 if (!CheckAutoReset()) {
639 return;
640 }
641 if (!isMoveEventValid_) {
642 HandleReset();
643 }
644 if (CheckChoosePoint(currentPoint_.first, currentPoint_.second)) {
645 return;
646 }
647
648 auto host = GetHost();
649 CHECK_NULL_VOID(host);
650 OffsetF touchPoint;
651 auto geometryNode = host->GetGeometryNode();
652 CHECK_NULL_VOID(geometryNode);
653 OffsetF contentOffset = geometryNode->GetContentOffset();
654 float sideLength = geometryNode->GetContentSize().Width();
655 float offset = sideLength / PATTERN_LOCK_COL_COUNT / RADIUS_TO_DIAMETER;
656 float offsetX = contentOffset.GetX() + offset * (currentPoint_.first * 2 - 1);
657 float offsetY = contentOffset.GetY() + offset * (currentPoint_.second * 2 - 1);
658 touchPoint.SetX(offsetX);
659 touchPoint.SetY(offsetY);
660 cellCenter_ = touchPoint;
661
662 AddPassPoint(currentPoint_.first, currentPoint_.second);
663 choosePoint_.emplace_back(currentPoint_.first, currentPoint_.second);
664 StartModifierConnectedAnimate(currentPoint_.first, currentPoint_.second);
665 UpdateDotConnectEvent();
666 isOnKeyEventState_ = true;
667
668 isMoveEventValid_ = true;
669 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
670 }
671
PaintFocusState()672 void PatternLockPattern::PaintFocusState()
673 {
674 auto host = GetHost();
675 CHECK_NULL_VOID(host);
676 auto focusHub = host->GetFocusHub();
677 CHECK_NULL_VOID(focusHub);
678 focusHub->PaintFocusState(true);
679
680 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
681 }
682
OnKeyDrapUp()683 void PatternLockPattern::OnKeyDrapUp()
684 {
685 if (currentPoint_.second != 1) {
686 currentPoint_ = { currentPoint_.first, currentPoint_.second - 1 };
687 PaintFocusState();
688 }
689 }
690
OnKeyDrapDown()691 void PatternLockPattern::OnKeyDrapDown()
692 {
693 if (currentPoint_.second != PATTERN_LOCK_COL_COUNT) {
694 currentPoint_ = { currentPoint_.first, currentPoint_.second + 1 };
695 PaintFocusState();
696 }
697 }
698
OnKeyDrapLeft()699 void PatternLockPattern::OnKeyDrapLeft()
700 {
701 if (currentPoint_.first != 1) {
702 currentPoint_ = { currentPoint_.first - 1, currentPoint_.second };
703 PaintFocusState();
704 }
705 }
706
OnKeyDrapRight()707 void PatternLockPattern::OnKeyDrapRight()
708 {
709 if (currentPoint_.first != PATTERN_LOCK_COL_COUNT) {
710 currentPoint_ = { currentPoint_.first + 1, currentPoint_.second };
711 PaintFocusState();
712 }
713 }
714
OnKeyEvent(const KeyEvent & event)715 bool PatternLockPattern::OnKeyEvent(const KeyEvent& event)
716 {
717 if (event.action != KeyAction::DOWN) {
718 return false;
719 }
720 switch (event.code) {
721 case KeyCode::KEY_SPACE:
722 OnFocusClick();
723 return true;
724 case KeyCode::KEY_ENTER:
725 if (isMoveEventValid_) {
726 AddPointEnd();
727 isOnKeyEventState_ = false;
728 }
729 return true;
730 case KeyCode::KEY_DPAD_UP:
731 OnKeyDrapUp();
732 return true;
733 case KeyCode::KEY_DPAD_DOWN:
734 OnKeyDrapDown();
735 return true;
736 case KeyCode::KEY_DPAD_LEFT:
737 OnKeyDrapLeft();
738 return true;
739 case KeyCode::KEY_DPAD_RIGHT:
740 OnKeyDrapRight();
741 return true;
742 case KeyCode::KEY_MOVE_HOME:
743 currentPoint_ = { 1, 1 };
744 PaintFocusState();
745 return true;
746 case KeyCode::KEY_MOVE_END:
747 currentPoint_ = { PATTERN_LOCK_COL_COUNT, PATTERN_LOCK_COL_COUNT };
748 PaintFocusState();
749 return true;
750 case KeyCode::KEY_ESCAPE:
751 HandleReset();
752 return true;
753 default:
754 break;
755 }
756 return false;
757 }
758
InitMouseEvent()759 void PatternLockPattern::InitMouseEvent()
760 {
761 auto host = GetHost();
762 CHECK_NULL_VOID(host);
763 auto eventHub = host->GetEventHub<EventHub>();
764 CHECK_NULL_VOID(eventHub);
765 auto inputEventHub = eventHub->GetOrCreateInputEventHub();
766 CHECK_NULL_VOID(inputEventHub);
767 auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
768 auto pattern = weak.Upgrade();
769 CHECK_NULL_VOID(pattern);
770 pattern->HandleHoverEvent(isHover);
771 };
772 auto hoverEvent = MakeRefPtr<InputEvent>(std::move(hoverTask));
773 CHECK_NULL_VOID(hoverEvent);
774 inputEventHub->AddOnHoverEvent(hoverEvent);
775
776 auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
777 auto pattern = weak.Upgrade();
778 CHECK_NULL_VOID(pattern);
779 pattern->HandleMouseEvent(info);
780 };
781 auto mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
782 inputEventHub->AddOnMouseEvent(mouseEvent_);
783 }
784
HandleHoverEvent(bool isHover)785 void PatternLockPattern::HandleHoverEvent(bool isHover)
786 {
787 CHECK_NULL_VOID(patternLockModifier_);
788 patternLockModifier_->SetIsHover(isHover);
789 }
790
HandleMouseEvent(const MouseInfo & info)791 void PatternLockPattern::HandleMouseEvent(const MouseInfo& info)
792 {
793 OffsetF hoverPoint;
794 hoverPoint.SetX(info.GetLocalLocation().GetX());
795 hoverPoint.SetY(info.GetLocalLocation().GetY());
796 cellCenter_ = hoverPoint;
797 bool isPointHover = false;
798 for (int32_t i = 0; i < PATTERN_LOCK_COL_COUNT; i++) {
799 for (int32_t j = 0; j < PATTERN_LOCK_COL_COUNT; j++) {
800 if (CheckInHotSpot(hoverPoint, i + 1, j + 1)) {
801 CHECK_NULL_VOID(patternLockModifier_);
802 patternLockModifier_->SetHoverIndex(i * PATTERN_LOCK_COL_COUNT + j);
803 isPointHover = true;
804 break;
805 }
806 }
807 }
808 if (!isPointHover) {
809 patternLockModifier_->SetHoverIndex(-1);
810 }
811 }
812
StartModifierConnectedAnimate(int32_t x,int32_t y)813 void PatternLockPattern::StartModifierConnectedAnimate(int32_t x, int32_t y)
814 {
815 CHECK_NULL_VOID(patternLockModifier_);
816 patternLockModifier_->StartConnectedCircleAnimate(x, y);
817 patternLockModifier_->StartConnectedLineAnimate(x, y);
818 }
819
StartModifierAddPassPointAnimate(int32_t x,int32_t y)820 void PatternLockPattern::StartModifierAddPassPointAnimate(int32_t x, int32_t y)
821 {
822 CHECK_NULL_VOID(patternLockModifier_);
823 patternLockModifier_->StartConnectedCircleAnimate(x, y);
824 }
825
StartModifierCanceledAnimate()826 void PatternLockPattern::StartModifierCanceledAnimate()
827 {
828 CHECK_NULL_VOID(patternLockModifier_);
829 if (isMoveEventValid_) {
830 patternLockModifier_->StartCanceledAnimate();
831 }
832 }
833
GetLastChoosePointOffset()834 OffsetF PatternLockPattern::GetLastChoosePointOffset()
835 {
836 OffsetF cellCenter;
837 auto host = GetHost();
838 CHECK_NULL_RETURN(host, cellCenter);
839 auto geometryNode = host->GetGeometryNode();
840 CHECK_NULL_RETURN(geometryNode, cellCenter);
841 float sideLength = geometryNode->GetContentSize().Width();
842 auto offset = geometryNode->GetContentOffset();
843 auto lastPoint = choosePoint_.back();
844 cellCenter.SetX(offset.GetX() + sideLength / PATTERN_LOCK_COL_COUNT / RADIUS_TO_DIAMETER *
845 (lastPoint.GetColumn() * RADIUS_TO_DIAMETER - 1));
846 cellCenter.SetY(offset.GetY() + sideLength / PATTERN_LOCK_COL_COUNT / RADIUS_TO_DIAMETER *
847 (lastPoint.GetRow() * RADIUS_TO_DIAMETER - 1));
848 return cellCenter;
849 }
850
CalculateCellCenter()851 void PatternLockPattern::CalculateCellCenter()
852 {
853 if (isOnKeyEventState_) {
854 size_t count = choosePoint_.size();
855 if (count < 1) {
856 return;
857 }
858 cellCenter_ = GetLastChoosePointOffset();
859 } else {
860 cellCenter_ = screenTouchPoint_;
861 }
862 }
863
GetTouchOffsetToNode()864 OffsetF PatternLockPattern::GetTouchOffsetToNode()
865 {
866 auto host = GetHost();
867 CHECK_NULL_RETURN(host, OffsetF());
868 auto pipelineContext = PipelineBase::GetCurrentContext();
869 CHECK_NULL_RETURN(pipelineContext, OffsetF());
870 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
871 OffsetF nodeOffset = host->GetPositionToWindowWithTransform();
872 auto container = Container::CurrentSafely();
873 auto windowScale = container->GetWindowScale();
874 nodeOffset = nodeOffset * windowScale;
875 OffsetF offset(windowOffset.GetX() + nodeOffset.GetX(), windowOffset.GetY() + nodeOffset.GetY());
876 offset = screenTouchPoint_ - offset;
877 if (windowScale != 0) {
878 offset = offset / windowScale;
879 }
880 return offset;
881 }
882 } // namespace OHOS::Ace::NG
883