• 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/progress/render_bubble_progress.h"
17 
18 #include "base/log/event_report.h"
19 #include "core/components/progress/progress_theme.h"
20 
21 namespace OHOS::Ace {
22 namespace {
23 
24 constexpr double SIN_45 = 0.707;
25 constexpr double COS_45 = 0.707;
26 constexpr Color DARK_COLOR = Color(0xFF333333);
27 constexpr Color LIGHT_COLOR = Color(0xFF8A8A8A);
28 
29 } // namespace
30 
RenderBubbleProgress()31 RenderBubbleProgress::RenderBubbleProgress() : RenderNode(true) {}
32 
OnPostFlush()33 void RenderBubbleProgress::OnPostFlush()
34 {
35     static const int32_t totalTime = 8;
36     static const int32_t totalDuration = 4800;
37     RefPtr<CurveAnimation<double>> animation =
38         AceType::MakeRefPtr<CurveAnimation<double>>(0, totalTime, Curves::LINEAR);
39     animation->AddListener([weak = AceType::WeakClaim(this)](float progress) {
40         auto bubble = weak.Upgrade();
41         if (!bubble) {
42             return;
43         }
44         bubble->step_ = static_cast<int32_t>(progress);
45         float fraction = progress - bubble->step_;
46         auto evaluatorDarkToLight = AceType::MakeRefPtr<LinearEvaluator<Color>>();
47         bubble->lightToDark_ = evaluatorDarkToLight->Evaluate(Color(LIGHT_COLOR), Color(DARK_COLOR), fraction);
48         bubble->darkToLight_ = evaluatorDarkToLight->Evaluate(Color(DARK_COLOR), Color(LIGHT_COLOR), fraction);
49         bubble->MarkNeedRender();
50     });
51     animatorController_->AddInterpolator(animation);
52     animatorController_->SetDuration(totalDuration);
53     animatorController_->SetIteration(ANIMATION_REPEAT_INFINITE);
54     animatorController_->Play();
55     simulationPrepared_ = true;
56 }
57 
Update(const RefPtr<Component> & component)58 void RenderBubbleProgress::Update(const RefPtr<Component>& component)
59 {
60     if (!animatorController_) {
61         auto context = GetContext();
62         animatorController_ = AceType::MakeRefPtr<Animator>(context);
63         auto pipelineContext = context.Upgrade();
64         if (!pipelineContext) {
65             LOGE("context is nullptr");
66             return;
67         }
68         pipelineContext->AddPostFlushListener(AceType::Claim(this));
69     }
70 
71     auto bubbleProgress = AceType::DynamicCast<BubbleProgressComponent>(component);
72     if (!bubbleProgress) {
73         LOGE("Update with nullptr");
74         return;
75     }
76     diameter_ = NormalizeToPx(bubbleProgress->GetDiameter());
77     maxCircleRadius_ = NormalizeToPx(bubbleProgress->GetBubbleRadius());
78     MarkNeedLayout();
79 }
80 
PerformLayout()81 void RenderBubbleProgress::PerformLayout()
82 {
83     // the diameter will be constrain by layout size.
84     Size layoutSize;
85     auto theme = GetTheme<ProgressTheme>();
86     if (!NearEqual(diameter_, 0.0)) {
87         layoutSize = GetLayoutParam().Constrain(Size(diameter_, diameter_));
88     } else {
89         if (GetLayoutParam().GetMaxSize().IsInfinite()) {
90             double defaultDiameter = NormalizeToPx(theme->GetBubbleDiameter());
91             layoutSize = Size(defaultDiameter, defaultDiameter);
92         } else {
93             layoutSize = GetLayoutParam().GetMaxSize();
94         }
95     }
96 
97     // radius is half of the height or width
98     radius_ = std::min(layoutSize.Height(), layoutSize.Width()) / 2.0;
99     center_ = Vertex(layoutSize.Width() / 2.0, layoutSize.Height() / 2.0);
100 
101     // based on law of sines, when the r1 : r2 > 4.83 : 1, the circle will never be overlapped.
102     maxCircleRadius_ = NearEqual(maxCircleRadius_, 0.0) ? NormalizeToPx(theme->GetBubbleRadius()) : maxCircleRadius_;
103     SetLayoutSize(layoutSize);
104     CalculateCirclePosition();
105 }
106 
CalculateCirclePosition()107 void RenderBubbleProgress::CalculateCirclePosition()
108 {
109     double radius = radius_ - maxCircleRadius_;
110     subCircleCenter_.clear();
111     // Add bottom right points
112     subCircleCenter_.push_back(center_ + Vertex(0.0, radius));
113     subCircleCenter_.push_back(center_ + Vertex(SIN_45 * radius, COS_45 * radius));
114     subCircleCenter_.push_back(center_ + Vertex(radius, 0.0));
115 
116     // Add top right points
117     subCircleCenter_.push_back(center_ + Vertex(COS_45 * radius, -1 * SIN_45 * radius));
118     subCircleCenter_.push_back(center_ + Vertex(0.0, -1 * radius));
119 
120     // Add top left points
121     subCircleCenter_.push_back(center_ + Vertex(-1 * SIN_45 * radius, -1 * COS_45 * radius));
122     subCircleCenter_.push_back(center_ + Vertex(-1 * radius, 0.0));
123 
124     // Add bottom left points
125     subCircleCenter_.push_back(center_ + Vertex(-1 * SIN_45 * radius, COS_45 * radius));
126 }
127 
OnVisibleChanged()128 void RenderBubbleProgress::OnVisibleChanged()
129 {
130     AnimationChanged();
131 }
132 
OnHiddenChanged(bool hidden)133 void RenderBubbleProgress::OnHiddenChanged(bool hidden)
134 {
135     AnimationChanged();
136 }
137 
AnimationChanged()138 void RenderBubbleProgress::AnimationChanged()
139 {
140     if (!simulationPrepared_) {
141         return;
142     }
143     if (GetVisible() && !GetHidden()) {
144         if (animatorController_) {
145             animatorController_->Play();
146         } else {
147             LOGI("fail to start progress animation");
148         }
149     } else {
150         if (animatorController_) {
151             animatorController_->Pause();
152         } else {
153             LOGI("fail to stop progress animation");
154         }
155     }
156 }
157 
OnAppShow()158 void RenderBubbleProgress::OnAppShow()
159 {
160     RenderNode::OnAppShow();
161     AnimationChanged();
162 }
163 
OnAppHide()164 void RenderBubbleProgress::OnAppHide()
165 {
166     RenderNode::OnAppHide();
167     AnimationChanged();
168 }
169 
170 }
171