• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_v2/pattern_lock/render_pattern_lock.h"
17 
18 namespace OHOS::Ace::V2 {
RenderPatternLock()19 RenderPatternLock::RenderPatternLock()
20 {
21     touchRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
22     auto weak = AceType::WeakClaim(this);
23     touchRecognizer_->SetOnTouchDown([weak](const TouchEventInfo& info) {
24         auto patternLock = weak.Upgrade();
25         if (patternLock && !info.GetTouches().empty()) {
26             const auto& locationInfo = info.GetTouches().front();
27             double moveDeltaX = locationInfo.GetLocalLocation().GetX();
28             double moveDeltaY = locationInfo.GetLocalLocation().GetY();
29             Offset touchPoint;
30             touchPoint.SetX(moveDeltaX);
31             touchPoint.SetY(moveDeltaY);
32             patternLock->HandleCellTouchDown(touchPoint);
33         }
34     });
35     touchRecognizer_->SetOnTouchMove([weak](const TouchEventInfo& info) {
36         auto patternLock = weak.Upgrade();
37         if (patternLock && !info.GetTouches().empty()) {
38             const auto& locationInfo = info.GetTouches().front();
39             double moveDeltaX = locationInfo.GetLocalLocation().GetX();
40             double moveDeltaY = locationInfo.GetLocalLocation().GetY();
41             Offset touchPoint;
42             touchPoint.SetX(moveDeltaX);
43             touchPoint.SetY(moveDeltaY);
44             patternLock->HandleCellTouchMove(touchPoint);
45         }
46     });
47     touchRecognizer_->SetOnTouchUp([weak](const TouchEventInfo& info) {
48         auto patternLock = weak.Upgrade();
49         if (patternLock) {
50             patternLock->HandleCellTouchUp();
51         }
52     });
53     touchRecognizer_->SetOnTouchCancel([weak](const TouchEventInfo& info) {
54         auto patternLock = weak.Upgrade();
55         if (patternLock) {
56             patternLock->HandleCellTouchCancel();
57         }
58     });
59 }
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)60 void RenderPatternLock::OnTouchTestHit(
61     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
62 {
63     touchRecognizer_->SetCoordinateOffset(coordinateOffset);
64     result.emplace_back(touchRecognizer_);
65 }
HandleCellTouchDown(const Offset & offset)66 void RenderPatternLock::HandleCellTouchDown(const Offset& offset)
67 {
68     if (!CheckAutoReset()) {
69         return;
70     }
71     HandleReset();
72     cellCenter_ = offset;
73     bool isAdd = false;
74     for (int16_t i = 0; i < COL_COUNT && !isAdd; i++) {
75         for (int16_t j = 0; j < COL_COUNT && !isAdd; j++) {
76             isAdd = AddChoosePoint(offset, i + 1, j + 1);
77         }
78     }
79     MarkNeedRender();
80     isMoveEventValid_ = true;
81 }
HandleCellTouchMove(const Offset & offset)82 void RenderPatternLock::HandleCellTouchMove(const Offset& offset)
83 {
84     if (!isMoveEventValid_) {
85         return;
86     }
87     cellCenter_ = offset;
88     bool isAdd = false;
89     for (int16_t i = 0; i < COL_COUNT && !isAdd; i++) {
90         for (int16_t j = 0; j < COL_COUNT && !isAdd; j++) {
91             isAdd = AddChoosePoint(offset, i + 1, j + 1);
92         }
93     }
94     MarkNeedRender();
95 }
HandleCellTouchUp()96 void RenderPatternLock::HandleCellTouchUp()
97 {
98     if (!CheckAutoReset()) {
99         return;
100     }
101     animator_->Finish();
102     isMoveEventValid_ = false;
103     std::vector<int> chooseCellVec;
104     for (auto it = choosePoint_.begin(); it != choosePoint_.end(); it++) {
105         chooseCellVec.push_back((*it).GetCode());
106     }
107     if (callbackForJS_) {
108         auto event = std::make_shared<PatternCompleteEvent>(chooseCellVec);
109         if (event) {
110             callbackForJS_(event);
111         }
112     }
113     animator_->SetDuration(DOWN_DURATION);
114     animator_->Forward();
115     MarkNeedRender();
116 }
117 
HandleCellTouchCancel()118 void RenderPatternLock::HandleCellTouchCancel()
119 {
120     HandleCellTouchUp();
121 }
UpdateAttr(const RefPtr<Component> & component)122 void RenderPatternLock::UpdateAttr(const RefPtr<Component>& component)
123 {
124     const auto& patternLockComponent = AceType::DynamicCast<PatternLockComponent>(component);
125     if (!patternLockComponent) {
126         LOGE("PatternLockComponent is null!");
127         return;
128     }
129     sideLength_ = patternLockComponent->GetSideLength().Value() < 0.0 ? 0.0_vp : patternLockComponent->GetSideLength();
130     double cSideLength = patternLockComponent->GetSideLength().ConvertToVp();
131     double cCircleRadius = patternLockComponent->GetCircleRadius().ConvertToVp();
132     const int16_t radiusCount = COL_COUNT * RADIUS_TO_DIAMETER;
133     double handleCircleRadius = cCircleRadius > cSideLength / SCALE_SELECTED_CIRCLE_RADIUS / radiusCount
134                                     ? cSideLength / SCALE_SELECTED_CIRCLE_RADIUS / radiusCount
135                                     : cCircleRadius;
136     circleRadius_ = Dimension(handleCircleRadius < 0 ? 0 : handleCircleRadius, DimensionUnit::VP);
137     double cStrokeWidth = patternLockComponent->GetStrokeWidth().ConvertToVp();
138     double handleStrokeWidth = cStrokeWidth > cSideLength / COL_COUNT ? cSideLength / COL_COUNT : cStrokeWidth;
139     strokeWidth_ = Dimension(handleStrokeWidth < 0 ? 0 : handleStrokeWidth, DimensionUnit::VP);
140     circleRadiusAnimatorToIncrease_ = circleRadius_;
141     circleRadiusAnimatorToDecrease_ = circleRadius_ * SCALE_ACTIVE_CIRCLE_RADIUS;
142     regularColor_ = patternLockComponent->GetRegularColor();
143     selectedColor_ = patternLockComponent->GetSelectedColor();
144     activeColor_ = patternLockComponent->GetActiveColor();
145     pathColor_ = patternLockComponent->GetPathColor();
146     autoReset_ = patternLockComponent->GetAutoReset();
147     callbackForJS_ = AceAsyncEvent<void(const std::shared_ptr<PatternCompleteEvent>&)>::Create(
148         patternLockComponent->GetPatternCompleteEvent(), context_);
149     patternLockController_ = patternLockComponent->GetPatternLockController();
150     if (patternLockController_) {
151         auto weak = AceType::WeakClaim(this);
152         patternLockController_->SetResetImpl([weak]() {
153             auto patternLock = weak.Upgrade();
154             if (patternLock) {
155                 patternLock->HandleReset();
156             }
157         });
158     }
159 }
Update(const RefPtr<Component> & component)160 void RenderPatternLock::Update(const RefPtr<Component>& component)
161 {
162     UpdateAttr(component);
163     // animator
164     if (!animator_) {
165         animator_ = CREATE_ANIMATOR(GetContext());
166         auto touchAnimation = AceType::MakeRefPtr<CurveAnimation<double>>(0.0, 1.0, Curves::SHARP);
167         touchAnimation->AddListener([weak = AceType::WeakClaim(this)](double value) {
168             auto patternLock = weak.Upgrade();
169             if (patternLock) {
170                 Dimension radiusFir { patternLock->circleRadius_.ConvertToVp() *
171                                           (1 + (SCALE_SELECTED_CIRCLE_RADIUS - 1) * value),
172                     DimensionUnit::VP };
173                 patternLock->circleRadiusAnimatorToIncrease_ = radiusFir;
174                 double decreaseRate = 1 + (1 - value) * (SCALE_DECREASE - 1);
175                 Dimension radiusSec { patternLock->circleRadius_.ConvertToVp() * SCALE_ACTIVE_CIRCLE_RADIUS *
176                                           decreaseRate,
177                     DimensionUnit::VP };
178                 patternLock->circleRadiusAnimatorToDecrease_ = radiusSec;
179                 patternLock->MarkNeedRender();
180             }
181         });
182         animator_->ClearInterpolators();
183         animator_->AddInterpolator(touchAnimation);
184         animator_->SetFillMode(FillMode::FORWARDS);
185     }
186     MarkNeedLayout();
187 }
PerformLayout()188 void RenderPatternLock::PerformLayout()
189 {
190     Size layoutSizeAfterConstrain =
191         GetLayoutParam().Constrain(Size(NormalizeToPx(sideLength_), NormalizeToPx(sideLength_)));
192     SetLayoutSize(layoutSizeAfterConstrain);
193 }
AddChoosePoint(Offset offset,int16_t x,int16_t y)194 bool RenderPatternLock::AddChoosePoint(Offset offset, int16_t x, int16_t y)
195 {
196     const int16_t scale = RADIUS_TO_DIAMETER;
197     double offsetX = NormalizeToPx(sideLength_) / COL_COUNT / scale * (scale * x - 1);
198     double offsetY = NormalizeToPx(sideLength_) / COL_COUNT / scale * (scale * y - 1);
199     Offset centerOffset;
200     centerOffset.SetX(offsetX);
201     centerOffset.SetY(offsetY);
202     double distance = (offset - centerOffset).GetDistance();
203     if (distance <= (NormalizeToPx(circleRadius_) * SCALE_SELECTED_CIRCLE_RADIUS)) {
204         if (!CheckChoosePoint(x, y)) {
205             AddPassPoint(offset, x, y);
206             animator_->SetDuration(DOWN_DURATION);
207             animator_->Forward();
208             choosePoint_.push_back(PatternLockCell(x, y));
209         }
210         return true;
211     }
212     return false;
213 }
HandleReset()214 void RenderPatternLock::HandleReset()
215 {
216     isMoveEventValid_ = false;
217     choosePoint_.clear();
218     cellCenter_ = Offset::Zero();
219     MarkNeedRender();
220 }
GetCircleCenterByXY(const Offset & offset,int16_t x,int16_t y)221 Offset RenderPatternLock::GetCircleCenterByXY(const Offset& offset, int16_t x, int16_t y)
222 {
223     const int16_t scale = RADIUS_TO_DIAMETER;
224     Offset cellCenter;
225     cellCenter.SetX(offset.GetX() + NormalizeToPx(sideLength_) / COL_COUNT / scale * (x * scale - 1));
226     cellCenter.SetY(offset.GetY() + NormalizeToPx(sideLength_) / COL_COUNT / scale * (y * scale - 1));
227     return cellCenter;
228 }
CheckChoosePoint(int16_t x,int16_t y) const229 bool RenderPatternLock::CheckChoosePoint(int16_t x, int16_t y) const
230 {
231     for (auto it = choosePoint_.begin(); it != choosePoint_.end(); it++) {
232         if ((*it).GetColumn() == x && (*it).GetRow() == y) {
233             return true;
234         }
235     }
236     return false;
237 }
CheckChoosePointIsLastIndex(int16_t x,int16_t y,int16_t index) const238 bool RenderPatternLock::CheckChoosePointIsLastIndex(int16_t x, int16_t y, int16_t index) const
239 {
240     if (!choosePoint_.empty() && static_cast<int16_t>(choosePoint_.size()) >= index) {
241         if (choosePoint_.at(choosePoint_.size() - static_cast<uint32_t>(index)).GetColumn() == x &&
242             choosePoint_.at(choosePoint_.size() - static_cast<uint32_t>(index)).GetRow() == y) {
243             return true;
244         }
245     }
246     return false;
247 }
CheckAutoReset() const248 bool RenderPatternLock::CheckAutoReset() const
249 {
250     if (!autoReset_ && !choosePoint_.empty() && !isMoveEventValid_) {
251         return false;
252     }
253     return true;
254 }
AddPassPoint(Offset offset,int16_t x,int16_t y)255 void RenderPatternLock::AddPassPoint(Offset offset, int16_t x, int16_t y)
256 {
257     if (choosePoint_.empty()) {
258         return;
259     }
260     passPointCount_ = 0;
261     PatternLockCell lastCell = choosePoint_.back();
262     int16_t lastX = lastCell.GetColumn();
263     int16_t lastY = lastCell.GetRow();
264     int16_t lastCode = lastCell.GetCode();
265     int16_t nowCode = COL_COUNT * (y - 1) + (x - 1);
266     std::vector<PatternLockCell> passPointVec;
267     for (int16_t i = 1; i <= COL_COUNT; i++) {
268         for (int16_t j = 1; j <= COL_COUNT; j++) {
269             PatternLockCell passPoint = PatternLockCell(i, j);
270             if ((passPoint.GetCode() >= nowCode && passPoint.GetCode() >= lastCode) ||
271                 (passPoint.GetCode() <= nowCode && passPoint.GetCode() <= lastCode)) {
272                 continue;
273             }
274             if ((j != y) && (j != lastY) &&
275                 ((double(lastX - i) / (lastY - j) == double(i - x) / (j - y)) && !CheckChoosePoint(i, j))) {
276                 passPointVec.push_back(passPoint);
277             }
278             if ((j == lastY) && (j == y) && !CheckChoosePoint(i, j)) {
279                 passPointVec.push_back(passPoint);
280             }
281         }
282     }
283     size_t passPointLength = passPointVec.size();
284     if (passPointLength == 0) {
285         return;
286     }
287     passPointCount_ = static_cast<int16_t>(passPointLength);
288     if (nowCode > lastCode) {
289         choosePoint_.push_back(passPointVec.front());
290         if (passPointLength > 1) {
291             choosePoint_.push_back(passPointVec.back());
292         }
293     } else {
294         choosePoint_.push_back(passPointVec.back());
295         if (passPointLength > 1) {
296             choosePoint_.push_back(passPointVec.front());
297         }
298     }
299 }
300 } // namespace OHOS::Ace::V2
301