• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/drag_bar/render_drag_bar.h"
17 
18 #include "core/animation/curve.h"
19 #include "core/animation/curve_animation.h"
20 #include "core/animation/curves.h"
21 #include "core/animation/keyframe.h"
22 #include "core/animation/keyframe_animation.h"
23 #include "core/components/drag_bar/drag_bar_component.h"
24 
25 namespace OHOS::Ace {
26 namespace {
27 
28 constexpr Dimension DRAG_ICON_WIDTH = 64.0_vp;
29 constexpr Dimension DRAG_ICON_HEIGHT = 24.0_vp;
30 constexpr Dimension HOT_REGION_WIDTH = 64.0_vp;
31 constexpr Dimension HOT_REGION_HEIGHT = 24.0_vp;
32 constexpr Dimension PAINT_WIDTH = 56.0_vp;
33 constexpr Dimension PAINT_HEIGHT = 8.0_vp;
34 constexpr Dimension MAX_DRAG_X = 10.0_vp;
35 constexpr Dimension MAX_DRAG_Y = 4.0_vp;
36 constexpr double DRAG_X_RATIO = 0.4;
37 constexpr double DRAG_Y_RATIO = 0.2;
38 constexpr double SCALE_ICON = 1.15;
39 constexpr double SCALE_WIDTH = 1.5 / SCALE_ICON;
40 constexpr int32_t DOWN_DURATION = 150;
41 constexpr int32_t RESET_DURATION = 250;
42 constexpr int32_t STYLE_DURATION = 200;
43 
44 // For DragBar Shrink State Point.
45 const Offset POINT_L_SHRINK = Offset(17.0, 15.0); // Left Point position.
46 const Offset POINT_C_SHRINK = Offset(32.0, 9.0);  // Center Point position.
47 const Offset POINT_R_SHRINK = Offset(47.0, 15.0); // Right Point position.
48 
49 // For DragBar Initial State Point.
50 const Offset POINT_L_INITIAL = Offset(18.0, 12.0); // Left Point position.
51 const Offset POINT_C_INITIAL = Offset(32.0, 12.0); // Center Point position.
52 const Offset POINT_R_INITIAL = Offset(46.0, 12.0); // Right Point position.
53 
54 // For DragBar Expand State Point.
55 const Offset POINT_L_EXPAND = Offset(17.0, 9.0);  // Left Point position.
56 const Offset POINT_C_EXPAND = Offset(32.0, 15.0); // Center Point position.
57 const Offset POINT_R_EXPAND = Offset(47.0, 9.0);  // Right Point position.
58 
59 const Size DRAG_BAR_SIZE = Size(64.0, 24.0);
60 
61 constexpr double OPACITY_DEFAULT = 0.2;
62 
63 } // namespace
64 
Update(const RefPtr<Component> & component)65 void RenderDragBar::Update(const RefPtr<Component>& component)
66 {
67     if (!animator_) {
68         animator_ = CREATE_ANIMATOR(GetContext());
69     }
70     if (!barTouchController_) {
71         barTouchController_ = CREATE_ANIMATOR(GetContext());
72         auto touchAnimation = AceType::MakeRefPtr<CurveAnimation<double>>(1.0, SCALE_ICON, Curves::SHARP);
73         touchAnimation->AddListener([weak = AceType::WeakClaim(this)](double value) {
74             auto dragBar = weak.Upgrade();
75             if (dragBar) {
76                 dragBar->scaleIcon_ = value;
77                 dragBar->scaleWidth_ = 1.0 + (value - 1.0) / (SCALE_ICON - 1.0) * (SCALE_WIDTH - 1.0);
78                 dragBar->MarkNeedRender();
79             }
80         });
81         barTouchController_->ClearInterpolators();
82         barTouchController_->AddInterpolator(touchAnimation);
83         barTouchController_->SetFillMode(FillMode::FORWARDS);
84     }
85     if (!barRangeController_) {
86         barRangeController_ = CREATE_ANIMATOR(GetContext());
87         barRangeController_->SetFillMode(FillMode::FORWARDS);
88         barRangeController_->SetDuration(RESET_DURATION);
89     }
90     if (!barStyleController_) {
91         barStyleController_ = CREATE_ANIMATOR(GetContext());
92         barStyleController_->SetFillMode(FillMode::FORWARDS);
93         barStyleController_->SetDuration(STYLE_DURATION);
94     }
95     hotRegionHeight_ = HOT_REGION_HEIGHT;
96     dragRangeX_ = NormalizeToPx(MAX_DRAG_X);
97     dragRangeY_ = NormalizeToPx(MAX_DRAG_Y);
98     alpha_ = std::floor(UINT8_MAX * OPACITY_DEFAULT);
99     auto dragBar = AceType::DynamicCast<DragBarComponent>(component);
100     if (dragBar) {
101         showMode_ = dragBar->GetPanelMode();
102         hasDragBar_ = dragBar->HasDragBar();
103     }
104     InitializeRecognizer();
105     UpdateDrawPoint();
106     MarkNeedLayout();
107 }
108 
PerformLayout()109 void RenderDragBar::PerformLayout()
110 {
111     Size dragBarSize;
112     if (hasDragBar_) {
113         dragBarSize = Size(NormalizeToPx(HOT_REGION_WIDTH), NormalizeToPx(hotRegionHeight_));
114     }
115     if (fullScreenMode_) {
116         dragBarSize = Size(GetLayoutParam().GetMaxSize().Width(), NormalizeToPx(hotRegionHeight_));
117     }
118     auto realSize = Size(NormalizeToPx(DRAG_ICON_WIDTH), NormalizeToPx(DRAG_ICON_HEIGHT));
119     iconOffset_ = Alignment::GetAlignPosition(dragBarSize, realSize, Alignment::CENTER);
120     scaleX_ = realSize.Width() / DRAG_BAR_SIZE.Width();
121     scaleY_ = realSize.Height() / DRAG_BAR_SIZE.Height();
122     SetLayoutSize(dragBarSize);
123     imgTouchRegion_ = GetPaintRect();
124 }
125 
ShowArrow(bool show)126 void RenderDragBar::ShowArrow(bool show)
127 {
128     PanelMode mode = PanelMode::HALF;
129     if (show) {
130         mode = PanelMode::FULL;
131     } else {
132         mode = PanelMode::HALF;
133     }
134     ShowInPanelMode(mode);
135 }
136 
ShowInPanelMode(PanelMode mode)137 void RenderDragBar::ShowInPanelMode(PanelMode mode)
138 {
139     if (showMode_ == mode) {
140         return;
141     }
142     showMode_ = mode;
143     UpdateDrawPoint();
144     MarkNeedRender();
145 }
146 
UpdateDrawPoint()147 void RenderDragBar::UpdateDrawPoint()
148 {
149     Offset leftPoint, centerPoint, rightPoint;
150     switch (showMode_) {
151         case PanelMode::MINI:
152             leftPoint = POINT_L_SHRINK;
153             centerPoint = POINT_C_SHRINK;
154             rightPoint = POINT_R_SHRINK;
155             break;
156         case PanelMode::HALF:
157             leftPoint = POINT_L_INITIAL;
158             centerPoint = POINT_C_INITIAL;
159             rightPoint = POINT_R_INITIAL;
160             break;
161         case PanelMode::FULL:
162             leftPoint = POINT_L_EXPAND;
163             centerPoint = POINT_C_EXPAND;
164             rightPoint = POINT_R_EXPAND;
165             break;
166         default:
167             LOGE("Unsupported Show Mode:%{public}d", showMode_);
168             return;
169     }
170     if (barLeftPoint_ == Offset()) {
171         // No need to do animation when first time to display.
172         barLeftPoint_ = leftPoint;
173         barCenterPoint_ = centerPoint;
174         barRightPoint_ = rightPoint;
175     } else {
176         DoStyleAnimation(leftPoint, centerPoint, rightPoint);
177     }
178 }
179 
DoStyleAnimation(const Offset & left,const Offset & center,const Offset & right)180 void RenderDragBar::DoStyleAnimation(const Offset& left, const Offset& center, const Offset& right)
181 {
182     if (barStyleController_->IsRunning()) {
183         barStyleController_->Stop();
184     }
185     auto leftAnimation = AceType::MakeRefPtr<CurveAnimation<Offset>>(barLeftPoint_, left, Curves::SHARP);
186     leftAnimation->AddListener([weak = AceType::WeakClaim(this)](const Offset& value) {
187         auto dragBar = weak.Upgrade();
188         if (dragBar) {
189             dragBar->barLeftPoint_ = value;
190             dragBar->MarkNeedRender();
191         }
192     });
193     auto centerAnimation = AceType::MakeRefPtr<CurveAnimation<Offset>>(barCenterPoint_, center, Curves::SHARP);
194     centerAnimation->AddListener([weak = AceType::WeakClaim(this)](const Offset& value) {
195         auto dragBar = weak.Upgrade();
196         if (dragBar) {
197             dragBar->barCenterPoint_ = value;
198         }
199     });
200     auto rightAnimation = AceType::MakeRefPtr<CurveAnimation<Offset>>(barRightPoint_, right, Curves::SHARP);
201     rightAnimation->AddListener([weak = AceType::WeakClaim(this)](const Offset& value) {
202         auto dragBar = weak.Upgrade();
203         if (dragBar) {
204             dragBar->barRightPoint_ = value;
205         }
206     });
207     barStyleController_->ClearInterpolators();
208     barStyleController_->AddInterpolator(leftAnimation);
209     barStyleController_->AddInterpolator(centerAnimation);
210     barStyleController_->AddInterpolator(rightAnimation);
211     barStyleController_->Play();
212 }
213 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)214 void RenderDragBar::OnTouchTestHit(
215     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
216 {
217     if (fullScreenMode_) {
218         return;
219     }
220     if (clickDetector_) {
221         clickDetector_->SetCoordinateOffset(coordinateOffset);
222         result.emplace_back(clickDetector_);
223     }
224     if (touchDetector_) {
225         touchDetector_->SetCoordinateOffset(coordinateOffset);
226         result.emplace_back(touchDetector_);
227     }
228 }
229 
InitializeRecognizer()230 void RenderDragBar::InitializeRecognizer()
231 {
232     if (!clickDetector_) {
233         clickDetector_ = AceType::MakeRefPtr<ClickRecognizer>();
234         clickDetector_->SetOnClick([weak = WeakClaim(this)](const ClickInfo& info) {
235             auto dragBar = weak.Upgrade();
236             if (dragBar) {
237                 dragBar->HandleClick(info.GetLocalLocation());
238             }
239         });
240     }
241     if (!touchDetector_) {
242         touchDetector_ = AceType::MakeRefPtr<RawRecognizer>();
243         touchDetector_->SetOnTouchDown([weak = AceType::WeakClaim(this)](const TouchEventInfo& info) {
244             auto dragBar = weak.Upgrade();
245             if (dragBar && !info.GetTouches().empty()) {
246                 dragBar->HandleTouchDown(info.GetTouches().front().GetGlobalLocation());
247             }
248         });
249         touchDetector_->SetOnTouchMove([weakDrag = AceType::WeakClaim(this)](const TouchEventInfo& info) {
250             auto dragBar = weakDrag.Upgrade();
251             if (dragBar && !info.GetTouches().empty()) {
252                 dragBar->HandleTouchMove(info.GetTouches().front().GetGlobalLocation());
253             }
254         });
255         touchDetector_->SetOnTouchUp([weakDrag = AceType::WeakClaim(this)](const TouchEventInfo& info) {
256             auto dragBar = weakDrag.Upgrade();
257             if (dragBar) {
258                 dragBar->HandleTouchUp();
259             }
260         });
261         touchDetector_->SetOnTouchCancel([weakDrag = AceType::WeakClaim(this)](const TouchEventInfo& info) {
262             auto dragBar = weakDrag.Upgrade();
263             if (dragBar) {
264                 dragBar->HandleTouchUp();
265             }
266         });
267     }
268 }
269 
HandleClick(const Offset & clickPosition)270 void RenderDragBar::HandleClick(const Offset& clickPosition)
271 {
272     if (!clickArrowCallback_) {
273         return;
274     }
275     clickArrowCallback_();
276 }
277 
HandleTouchDown(const Offset & downPoint)278 void RenderDragBar::HandleTouchDown(const Offset& downPoint)
279 {
280     // Display the click-to-magnify effect.
281     downPoint_ = downPoint;
282     barTouchController_->SetDuration(DOWN_DURATION);
283     barTouchController_->Forward();
284 }
285 
HandleTouchMove(const Offset & movePoint)286 void RenderDragBar::HandleTouchMove(const Offset& movePoint)
287 {
288     // Display the dragging offset effect.
289     Offset distance = movePoint - downPoint_;
290     Offset dragOffset;
291     dragOffset.SetX(std::clamp(distance.GetX() * DRAG_X_RATIO, -dragRangeX_, dragRangeX_));
292     dragOffset.SetY(std::clamp(distance.GetY() * DRAG_Y_RATIO, -dragRangeY_, dragRangeY_));
293     if (dragOffset_ != dragOffset) {
294         dragOffset_ = dragOffset;
295         MarkNeedRender();
296     }
297 }
298 
HandleTouchUp()299 void RenderDragBar::HandleTouchUp()
300 {
301     // Restore the click-to-magnify effect.
302     barTouchController_->SetDuration(RESET_DURATION);
303     barTouchController_->Backward();
304 
305     // Restore the dragging offset effect.
306     if (dragOffset_ == Offset()) {
307         return; // No need to back to center with animation.
308     }
309     auto dragAnimation = AceType::MakeRefPtr<CurveAnimation<Offset>>(dragOffset_, Offset(), Curves::SHARP);
310     dragAnimation->AddListener([weak = AceType::WeakClaim(this)](Offset value) {
311         auto dragBar = weak.Upgrade();
312         if (dragBar) {
313             dragBar->dragOffset_ = value;
314             dragBar->MarkNeedRender();
315         }
316     });
317     barRangeController_->ClearInterpolators();
318     barRangeController_->AddInterpolator(dragAnimation);
319     barRangeController_->Play();
320 }
321 
FadingOut()322 void RenderDragBar::FadingOut()
323 {
324     auto keyframeFrom = AceType::MakeRefPtr<Keyframe<double>>(0.0, 1.0);
325     auto keyframeTo = AceType::MakeRefPtr<Keyframe<double>>(1.0, 0.0);
326     auto animation = AceType::MakeRefPtr<KeyframeAnimation<double>>();
327     animation->AddKeyframe(keyframeFrom);
328     animation->AddKeyframe(keyframeTo);
329     animation->AddListener([weak = AceType::WeakClaim(this)](const double& opacity) {
330         auto dragBar = weak.Upgrade();
331         if (dragBar) {
332             dragBar->opacity_ = opacity;
333         }
334     });
335     animator_->AddInterpolator(animation);
336 }
337 
Stretching()338 void RenderDragBar::Stretching()
339 {
340     auto context = GetContext().Upgrade();
341     if (!context) {
342         LOGE("Animate to status bar failed. context is null.");
343         return;
344     }
345     auto keyframeFrom = AceType::MakeRefPtr<Keyframe<double>>(0.0, hotRegionHeight_.Value());
346     auto keyframeTo = AceType::MakeRefPtr<Keyframe<double>>(1.0, context->GetStatusBarHeight());
347     auto animation = AceType::MakeRefPtr<KeyframeAnimation<double>>();
348     animation->AddKeyframe(keyframeFrom);
349     animation->AddKeyframe(keyframeTo);
350     animation->AddListener([weak = AceType::WeakClaim(this)](const double& height) {
351         auto dragBar = weak.Upgrade();
352         if (!dragBar) {
353             return;
354         }
355         dragBar->hotRegionHeight_.SetValue(height);
356         dragBar->MarkNeedLayout();
357     });
358     animator_->AddStopListener([weak = AceType::WeakClaim(this)]() {
359         auto dragBar = weak.Upgrade();
360         if (!dragBar) {
361             return;
362         }
363         dragBar->SetFullScreenMode(true);
364         dragBar->MarkNeedLayout();
365     });
366     animator_->AddInterpolator(animation);
367 }
368 
AnimateToStatusBarPadding(int32_t duration)369 void RenderDragBar::AnimateToStatusBarPadding(int32_t duration)
370 {
371     if (animator_->IsRunning()) {
372         animator_->Finish();
373     }
374     animator_->ClearAllListeners();
375     animator_->ClearInterpolators();
376     Stretching();
377     FadingOut();
378     animator_->SetFillMode(FillMode::FORWARDS);
379     animator_->SetDuration(duration);
380     animator_->Forward();
381     SetDisableTouchEvent(true);
382 }
383 
SetStatusBarHeight(double height)384 void RenderDragBar::SetStatusBarHeight(double height)
385 {
386     // Reset full window animation.
387     if (animator_->IsRunning()) {
388         animator_->ClearAllListeners();
389         animator_->ClearInterpolators();
390         Stretching();
391         FadingOut();
392     }
393     if (GreatOrEqual(height, 0.0) && !NearEqual(statusBarHeight_.Value(), height)) {
394         statusBarHeight_.SetValue(height);
395         MarkNeedLayout();
396     }
397 }
398 
OnMouseHoverEnterTest()399 void RenderDragBar::OnMouseHoverEnterTest()
400 {
401     MarkNeedRender();
402 }
403 
OnMouseHoverExitTest()404 void RenderDragBar::OnMouseHoverExitTest()
405 {
406     MarkNeedRender();
407 }
408 
OnPaintFinish()409 void RenderDragBar::OnPaintFinish()
410 {
411     if (GetLayoutSize().IsEmpty()) {
412         return;
413     }
414     auto context = context_.Upgrade();
415     if (!context) {
416         return;
417     }
418     if (renderStatus_ == RenderStatus::FOCUS) {
419         Offset offset = GetPosition();
420         Size size = Size(NormalizeToPx(PAINT_WIDTH), NormalizeToPx(PAINT_HEIGHT));
421         auto alignOffset = Alignment::GetAlignPosition(GetLayoutSize(), size, Alignment::CENTER);
422         Offset globalOffset = GetGlobalOffset() + alignOffset;
423         RRect rrect = RRect::MakeRect(Rect(offset, size));
424         auto radius = Radius(size.Height() / 2);
425         rrect.SetCorner({ radius, radius, radius, radius });
426         context->ShowFocusAnimation(rrect, Color::BLUE, globalOffset);
427     }
428 }
429 
OnStatusChanged(RenderStatus renderStatus)430 void RenderDragBar::OnStatusChanged(RenderStatus renderStatus)
431 {
432     if (renderStatus_ != renderStatus) {
433         renderStatus_ = renderStatus;
434         MarkNeedRender();
435     }
436 }
437 
438 } // namespace OHOS::Ace
439