• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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