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/focus_animation/render_focus_animation.h"
17
18 #include "base/log/event_report.h"
19 #include "core/components/scroll/render_single_child_scroll.h"
20
21 namespace OHOS::Ace {
22 namespace {
23
24 constexpr int32_t TOTAL_DURATION = 3000;
25 constexpr float SEMICIRCLE = 180.0f;
26
27 } // namespace
28
Update(const RefPtr<Component> & component)29 void RenderFocusAnimation::Update(const RefPtr<Component>& component)
30 {
31 if (animationParamsSet_) {
32 return;
33 }
34 auto focusAnimation = AceType::DynamicCast<FocusAnimationComponent>(component);
35 if (!focusAnimation) {
36 LOGE("RenderFocusAnimation update with nullptr");
37 EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
38 return;
39 }
40
41 auto pipelineContext = GetContext().Upgrade();
42 if (!pipelineContext) {
43 LOGE("pipelineContext update with nullptr");
44 return;
45 }
46 auto theme = pipelineContext->GetThemeManager();
47 if (!theme) {
48 LOGE("calendar theme update with nullptr");
49 return;
50 }
51 focusTheme_ = theme->GetTheme<FocusAnimationTheme>();
52 layoutSize_.SetWidth(pipelineContext->GetRootWidth());
53 layoutSize_.SetHeight(pipelineContext->GetRootHeight());
54 if (SystemProperties::GetDeviceType() == DeviceType::TV) {
55 animator_ = CREATE_ANIMATOR(pipelineContext);
56 focusAnimation_ = AceType::MakeRefPtr<CurveAnimation<float>>(0.0f, SEMICIRCLE, Curves::LINEAR);
57 focusAnimation_->AddListener([weak = AceType::WeakClaim(this)](const float& value) {
58 auto client = weak.Upgrade();
59 if (client) {
60 client->progress_ = value;
61 client->MarkNeedRender(true);
62 }
63 });
64 animator_->AddInterpolator(focusAnimation_);
65 animator_->SetDuration(TOTAL_DURATION);
66 animator_->SetIteration(ANIMATION_REPEAT_INFINITE);
67 }
68
69 isDisplay_ = false;
70 animationParamsSet_ = true;
71 isRoot_ = focusAnimation->IsRoot();
72 }
73
MarkNeedRenderSpecial()74 bool RenderFocusAnimation::MarkNeedRenderSpecial()
75 {
76 auto parent = GetParent().Upgrade();
77 auto renderScroll = AceType::DynamicCast<RenderScroll>(parent);
78 if (renderScroll) {
79 return true;
80 }
81 return false;
82 }
83
SetFocusAnimationProperties(const RRect & rrect,const Offset & offset)84 void RenderFocusAnimation::SetFocusAnimationProperties(const RRect& rrect, const Offset& offset)
85 {
86 rrect_ = rrect;
87 offset_ = offset - GetGlobalOffset();
88 isNeedClip_ = false;
89 if (focusTheme_) {
90 pathColor_ = focusTheme_->GetColor();
91 }
92 animationParamsSet_ = true;
93 if ((offset_.GetX() + rrect.Width()) > layoutSize_.Width() && (offset_.GetX() + rrect.Width()) > 0) {
94 layoutSize_.SetWidth(offset_.GetX() + rrect.Width() + NormalizeToPx(blurMaskRadius_) * 2); // 2: two radius
95 MarkNeedLayout();
96 }
97 if ((offset_.GetY() + rrect.Height()) > layoutSize_.Height() && (offset_.GetY() + rrect.Height()) > 0) {
98 layoutSize_.SetHeight((offset_.GetY() + rrect.Height()) + NormalizeToPx(blurMaskRadius_) * 2); // 2: two radius
99 MarkNeedLayout();
100 }
101 }
102
SetFocusAnimationProperties(const RRect & rrect,const Color & color,const Offset & offset,bool isIndented)103 void RenderFocusAnimation::SetFocusAnimationProperties(
104 const RRect& rrect, const Color& color, const Offset& offset, bool isIndented)
105 {
106 SetFocusAnimationProperties(rrect, offset);
107 if (SystemProperties::GetDeviceType() == DeviceType::TV) {
108 pathColor_ = color;
109 if (!isDisplay_) {
110 isDisplay_ = true;
111 animator_->Play();
112 }
113 } else if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
114 if (isKeyEvent_) {
115 // When the device is phone, only the key event will require paint.
116 isDisplay_ = true;
117 isIndented_ = isIndented;
118 MarkNeedLayout();
119 }
120 }
121 }
122
SetFocusAnimationProperties(const RRect & rrect,const Color & color,const Offset & offset,const Rect & clipRect)123 void RenderFocusAnimation::SetFocusAnimationProperties(
124 const RRect& rrect, const Color& color, const Offset& offset, const Rect& clipRect)
125 {
126 if (SystemProperties::GetDeviceType() == DeviceType::TV) {
127 isNeedClip_ = true;
128 clipRect_ = clipRect;
129 }
130 SetFocusAnimationProperties(rrect, color, offset, false);
131 }
132
CancelFocusAnimation()133 void RenderFocusAnimation::CancelFocusAnimation()
134 {
135 isDisplay_ = false;
136 if (SystemProperties::GetDeviceType() == DeviceType::TV) {
137 animator_->Pause();
138 }
139 MarkNeedRender(true);
140 }
141
PerformLayout()142 void RenderFocusAnimation::PerformLayout()
143 {
144 SetLayoutSize(layoutSize_);
145 }
146
StopFocusAnimation()147 void RenderFocusAnimation::StopFocusAnimation()
148 {
149 if (SystemProperties::GetDeviceType() != DeviceType::TV) {
150 return;
151 }
152 animator_->Stop();
153 MarkNeedRender(true);
154 }
155
StartFocusAnimation()156 void RenderFocusAnimation::StartFocusAnimation()
157 {
158 isDisplay_ = true;
159 if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
160 MarkNeedRender();
161 } else if (SystemProperties::GetDeviceType() == DeviceType::TV) {
162 animator_->Play();
163 }
164 }
165
SetIsKeyEvent(bool isKeyEvent)166 void RenderFocusAnimation::SetIsKeyEvent(bool isKeyEvent)
167 {
168 isKeyEvent_ = isKeyEvent;
169 MarkNeedRender();
170 }
171
172 } // namespace OHOS::Ace
173