1 /*
2  * Copyright (c) 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 "core/components_ng/layout/layout_property.h"
17 #include "date_time_animation_controller.h"
18 
19 namespace OHOS::Ace::NG {
20 namespace {
21 constexpr int32_t CHILD_SIZE = 3;
22 constexpr double SEMI_CIRCLE_ANGEL = 180;
23 constexpr double OPACITY_DELAY = 100;
24 constexpr double COLUMN_OPACITY_DELAY = 150;
25 constexpr double OPACITY_DURATION = 150;
26 constexpr double TRIANGLE_DURATION = 300;
27 constexpr double MOVE_DURATION = 500;
28 } // namespace
PlayTitleInAnimation()29 void DateTimeAnimationController::PlayTitleInAnimation()
30 {
31     auto buttonIcon = buttonIcon_.Upgrade();
32     CHECK_NULL_VOID(buttonIcon);
33     auto renderContext = buttonIcon->GetRenderContext();
34     AnimationOption animationOption;
35     animationOption.SetDuration(TRIANGLE_DURATION);
36     animationOption.SetCurve(Curves::SHARP);
37 
38     renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0, 0));
39     AnimationUtils::Animate(animationOption,
40         [renderContext]() {
41             CHECK_NULL_VOID(renderContext);
42             renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0 - SEMI_CIRCLE_ANGEL, 0));
43         });
44 }
45 
PlayTitleOutAnimation()46 void DateTimeAnimationController::PlayTitleOutAnimation()
47 {
48     auto buttonIcon = buttonIcon_.Upgrade();
49     CHECK_NULL_VOID(buttonIcon);
50     auto renderContext = buttonIcon->GetRenderContext();
51     AnimationOption animationOption;
52     animationOption.SetDuration(TRIANGLE_DURATION);
53     animationOption.SetCurve(Curves::SHARP);
54 
55     renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0 - SEMI_CIRCLE_ANGEL, 0));
56     AnimationUtils::Animate(animationOption,
57         [renderContext]() {
58             CHECK_NULL_VOID(renderContext);
59             renderContext->UpdateTransformRotate(Vector5F(0, 0, 1, 0, 0));
60         });
61 }
62 
PlayMovingInAnimation()63 void DateTimeAnimationController::PlayMovingInAnimation()
64 {
65     auto year = year_.Upgrade();
66     CHECK_NULL_VOID(year);
67     auto month = month_.Upgrade();
68     CHECK_NULL_VOID(month);
69     auto day = day_.Upgrade();
70     CHECK_NULL_VOID(day);
71     auto yearRenderContext = year->GetRenderContext();
72     auto monthRenderContext = month->GetRenderContext();
73     auto dayRenderContext = day->GetRenderContext();
74     AnimationOption animationOption;
75     animationOption.SetDuration(MOVE_DURATION);
76     animationOption.SetCurve(Curves::FRICTION);
77 
78     yearRenderContext->UpdateTransformTranslate({ yearStart_, 0.0f, 0.0f });
79     monthRenderContext->UpdateTransformTranslate({ monthStart_, 0.0f, 0.0f });
80     dayRenderContext->UpdateTransformTranslate({ dayStart_, 0.0f, 0.0f });
81     AnimationUtils::Animate(animationOption,
82         [yearRenderContext, monthRenderContext, dayRenderContext, weak = AceType::WeakClaim(this)]() {
83             auto ref = weak.Upgrade();
84             CHECK_NULL_VOID(ref);
85             CHECK_NULL_VOID(yearRenderContext);
86             CHECK_NULL_VOID(monthRenderContext);
87             CHECK_NULL_VOID(dayRenderContext);
88             yearRenderContext->UpdateTransformTranslate({ ref->yearEnd_, 0.0f, 0.0f });
89             monthRenderContext->UpdateTransformTranslate({ ref->monthEnd_, 0.0f, 0.0f });
90             dayRenderContext->UpdateTransformTranslate({ ref->dayEnd_, 0.0f, 0.0f });
91         });
92 }
93 
PlayMovingOutAnimation()94 void DateTimeAnimationController::PlayMovingOutAnimation()
95 {
96     auto year = year_.Upgrade();
97     CHECK_NULL_VOID(year);
98     auto month = month_.Upgrade();
99     CHECK_NULL_VOID(month);
100     auto day = day_.Upgrade();
101     CHECK_NULL_VOID(day);
102     auto yearRenderContext = year->GetRenderContext();
103     auto monthRenderContext = month->GetRenderContext();
104     auto dayRenderContext = day->GetRenderContext();
105     AnimationOption animationOption;
106     animationOption.SetDuration(MOVE_DURATION);
107     animationOption.SetCurve(Curves::FRICTION);
108 
109     yearRenderContext->UpdateTransformTranslate({ yearEnd_, 0.0f, 0.0f });
110     monthRenderContext->UpdateTransformTranslate({ monthEnd_, 0.0f, 0.0f });
111     dayRenderContext->UpdateTransformTranslate({ dayEnd_, 0.0f, 0.0f });
112     AnimationUtils::Animate(animationOption,
113         [yearRenderContext, monthRenderContext, dayRenderContext, weak = AceType::WeakClaim(this)]() {
114             auto ref = weak.Upgrade();
115             CHECK_NULL_VOID(ref);
116             CHECK_NULL_VOID(yearRenderContext);
117             CHECK_NULL_VOID(monthRenderContext);
118             CHECK_NULL_VOID(dayRenderContext);
119             yearRenderContext->UpdateTransformTranslate({ ref->yearStart_, 0.0f, 0.0f });
120             monthRenderContext->UpdateTransformTranslate({ ref->monthStart_, 0.0f, 0.0f });
121             dayRenderContext->UpdateTransformTranslate({ ref->dayStart_, 0.0f, 0.0f });
122         });
123 }
124 
PlayOldColumnOpacityInAnimation()125 void DateTimeAnimationController::PlayOldColumnOpacityInAnimation()
126 {
127     auto monthDays = monthDays_.Upgrade();
128     CHECK_NULL_VOID(monthDays);
129     auto timePicker = timePicker_.Upgrade();
130     CHECK_NULL_VOID(timePicker);
131     auto monthDaysRender = monthDays->GetRenderContext();
132     auto timePickerRender = timePicker->GetRenderContext();
133     CHECK_NULL_VOID(monthDaysRender);
134     CHECK_NULL_VOID(timePickerRender);
135     auto datePicker = datePicker_.Upgrade();
136     if (datePicker) {
137         auto layoutProperty = datePicker->GetLayoutProperty<LayoutProperty>();
138         if (layoutProperty) {
139             layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
140         }
141     }
142     AnimationOption animationOption;
143     animationOption.SetDuration(OPACITY_DURATION);
144     animationOption.SetCurve(Curves::LINEAR);
145     animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
146         auto ref = weak.Upgrade();
147         CHECK_NULL_VOID(ref);
148         if (ref->isOutAnimationPlaying_) {
149             ref->isInAnimationPlaying_ = false;
150             return;
151         }
152         auto monthDaysNode = ref->monthDays_.Upgrade();
153         CHECK_NULL_VOID(monthDaysNode);
154         auto layoutProperty = monthDaysNode->GetLayoutProperty<LayoutProperty>();
155         CHECK_NULL_VOID(layoutProperty);
156         layoutProperty->UpdateVisibility(VisibleType::GONE);
157 
158         auto timePickerNode = ref->timePicker_.Upgrade();
159         CHECK_NULL_VOID(timePickerNode);
160         layoutProperty = timePickerNode->GetLayoutProperty<LayoutProperty>();
161         CHECK_NULL_VOID(layoutProperty);
162         layoutProperty->UpdateVisibility(VisibleType::GONE);
163         ref->isInAnimationPlaying_ = false;
164     });
165     monthDaysRender->UpdateOpacity(1);
166     timePickerRender->UpdateOpacity(1);
167     oldColumnOpacityInAnimation_ = AnimationUtils::StartAnimation(animationOption,
168         [monthDaysRender, timePickerRender]() {
169             CHECK_NULL_VOID(monthDaysRender);
170             CHECK_NULL_VOID(timePickerRender);
171             monthDaysRender->UpdateOpacity(0);
172             timePickerRender->UpdateOpacity(0);
173         }, animationOption.GetOnFinishEvent());
174 }
175 
PlayNewColumnOpacityInAnimation()176 void DateTimeAnimationController::PlayNewColumnOpacityInAnimation()
177 {
178     auto month = month_.Upgrade();
179     CHECK_NULL_VOID(month);
180     auto day = day_.Upgrade();
181     CHECK_NULL_VOID(day);
182     auto monthRender = month->GetRenderContext();
183     auto dayRender = day->GetRenderContext();
184     CHECK_NULL_VOID(monthRender);
185     CHECK_NULL_VOID(dayRender);
186 
187     AnimationOption animationOption;
188     animationOption.SetDuration(OPACITY_DURATION);
189     animationOption.SetCurve(Curves::LINEAR);
190 
191     monthRender->UpdateOpacity(0);
192     dayRender->UpdateOpacity(0);
193     AnimationUtils::Animate(animationOption,
194         [monthRender, dayRender]() {
195             CHECK_NULL_VOID(monthRender);
196             CHECK_NULL_VOID(dayRender);
197             monthRender->UpdateOpacity(1);
198             dayRender->UpdateOpacity(1);
199         });
200 }
201 
PlayYearColumnOpacityInAnimation()202 void DateTimeAnimationController::PlayYearColumnOpacityInAnimation()
203 {
204     auto year = year_.Upgrade();
205     CHECK_NULL_VOID(year);
206     auto yearRender = year->GetRenderContext();
207     CHECK_NULL_VOID(yearRender);
208 
209     AnimationOption animationOption;
210     animationOption.SetDelay(OPACITY_DELAY);
211     animationOption.SetDuration(OPACITY_DURATION);
212     animationOption.SetCurve(Curves::LINEAR);
213 
214     yearRender->OpacityAnimation(animationOption, 0.0f, 1.0f);
215 }
216 
PlayButtonOpacityInAnimation()217 void DateTimeAnimationController::PlayButtonOpacityInAnimation()
218 {
219     auto buttonRow = buttonRow_.Upgrade();
220     CHECK_NULL_VOID(buttonRow);
221     auto buttonRender = buttonRow->GetRenderContext();
222     CHECK_NULL_VOID(buttonRender);
223 
224     AnimationOption animationOption;
225     animationOption.SetDelay(OPACITY_DELAY);
226     animationOption.SetDuration(OPACITY_DURATION);
227     animationOption.SetCurve(Curves::LINEAR);
228     animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
229         auto ref = weak.Upgrade();
230         CHECK_NULL_VOID(ref);
231         auto buttonNode = ref->buttonRow_.Upgrade();
232         CHECK_NULL_VOID(buttonNode);
233         auto layoutProperty = buttonNode->GetLayoutProperty<LayoutProperty>();
234         CHECK_NULL_VOID(layoutProperty);
235         if (!ref->isDatePickerButtonHade_) {
236             layoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
237         }
238         auto focusHub = buttonNode->GetFocusHub();
239         CHECK_NULL_VOID(focusHub);
240         focusHub->SetShow(false);
241     });
242     if (!isDatePickerButtonHade_) {
243         buttonRender->OpacityAnimation(animationOption, 1.0f, 0.0f);
244     }
245 }
246 
PlayOldColumnOpacityOutAnimation()247 void DateTimeAnimationController::PlayOldColumnOpacityOutAnimation()
248 {
249     auto monthDays = monthDays_.Upgrade();
250     CHECK_NULL_VOID(monthDays);
251     auto monthDaysRender = monthDays->GetRenderContext();
252     auto timePicker = timePicker_.Upgrade();
253     CHECK_NULL_VOID(timePicker);
254     auto timePickerRender = timePicker->GetRenderContext();
255 
256     auto layoutProperty = monthDays->GetLayoutProperty<LayoutProperty>();
257     CHECK_NULL_VOID(layoutProperty);
258     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
259     layoutProperty = timePicker->GetLayoutProperty<LayoutProperty>();
260     CHECK_NULL_VOID(layoutProperty);
261     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
262 
263     AnimationOption animationOption;
264     animationOption.SetDelay(COLUMN_OPACITY_DELAY);
265     animationOption.SetDuration(OPACITY_DURATION);
266     animationOption.SetCurve(Curves::LINEAR);
267     animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
268         auto ref = weak.Upgrade();
269         CHECK_NULL_VOID(ref);
270         if (ref->isInAnimationPlaying_) {
271             ref->isOutAnimationPlaying_ = false;
272             return;
273         }
274         auto datePickerNode = ref->datePicker_.Upgrade();
275         CHECK_NULL_VOID(datePickerNode);
276         auto layoutProperty = datePickerNode->GetLayoutProperty<LayoutProperty>();
277         CHECK_NULL_VOID(layoutProperty);
278         layoutProperty->UpdateVisibility(VisibleType::GONE);
279         ref->isOutAnimationPlaying_ = false;
280     });
281 
282     monthDaysRender->UpdateOpacity(0);
283     timePickerRender->UpdateOpacity(0);
284     oldColumnOpacityOutAnimation_ = AnimationUtils::StartAnimation(animationOption,
285         [monthDaysRender, timePickerRender]() {
286             CHECK_NULL_VOID(monthDaysRender);
287             CHECK_NULL_VOID(timePickerRender);
288             monthDaysRender->UpdateOpacity(1);
289             timePickerRender->UpdateOpacity(1);
290         }, animationOption.GetOnFinishEvent());
291 }
292 
PlayNewColumnOpacityOutAnimation()293 void DateTimeAnimationController::PlayNewColumnOpacityOutAnimation()
294 {
295     auto month = month_.Upgrade();
296     CHECK_NULL_VOID(month);
297     auto day = day_.Upgrade();
298     CHECK_NULL_VOID(day);
299     auto monthRender = month->GetRenderContext();
300     auto dayRender = day->GetRenderContext();
301     CHECK_NULL_VOID(monthRender);
302     CHECK_NULL_VOID(dayRender);
303 
304     AnimationOption animationOption;
305     animationOption.SetDelay(OPACITY_DELAY);
306     animationOption.SetDuration(OPACITY_DURATION);
307     animationOption.SetCurve(Curves::LINEAR);
308 
309     monthRender->UpdateOpacity(1);
310     dayRender->UpdateOpacity(1);
311     AnimationUtils::Animate(animationOption,
312         [monthRender, dayRender]() {
313             CHECK_NULL_VOID(monthRender);
314             CHECK_NULL_VOID(dayRender);
315             monthRender->UpdateOpacity(0);
316             dayRender->UpdateOpacity(0);
317         });
318 }
319 
PlayYearColumnOpacityOutAnimation()320 void DateTimeAnimationController::PlayYearColumnOpacityOutAnimation()
321 {
322     auto year = year_.Upgrade();
323     CHECK_NULL_VOID(year);
324     auto yearRender = year->GetRenderContext();
325     CHECK_NULL_VOID(yearRender);
326 
327     AnimationOption animationOption;
328     animationOption.SetDuration(OPACITY_DURATION);
329     animationOption.SetCurve(Curves::LINEAR);
330 
331     yearRender->OpacityAnimation(animationOption, 1.0f, 0.0f);
332 }
333 
PlayButtonOpacityOutAnimation()334 void DateTimeAnimationController::PlayButtonOpacityOutAnimation()
335 {
336     auto buttonRow = buttonRow_.Upgrade();
337     CHECK_NULL_VOID(buttonRow);
338     auto buttonRender = buttonRow->GetRenderContext();
339     CHECK_NULL_VOID(buttonRender);
340 
341     AnimationOption animationOption;
342     animationOption.SetDelay(OPACITY_DELAY);
343     animationOption.SetDuration(OPACITY_DURATION);
344     animationOption.SetCurve(Curves::LINEAR);
345     animationOption.SetOnFinishEvent([weak = AceType::WeakClaim(this)] {
346         auto ref = weak.Upgrade();
347         CHECK_NULL_VOID(ref);
348         auto buttonNode = ref->buttonRow_.Upgrade();
349         CHECK_NULL_VOID(buttonNode);
350         auto layoutProperty = buttonNode->GetLayoutProperty<LayoutProperty>();
351         CHECK_NULL_VOID(layoutProperty);
352         layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
353         auto focusHub = buttonNode->GetFocusHub();
354         CHECK_NULL_VOID(focusHub);
355         focusHub->SetShow(true);
356     });
357     buttonRender->OpacityAnimation(animationOption, 0.0f, 1.0f);
358 }
359 
StopOldColumnOpacityInAnimation()360 void DateTimeAnimationController::StopOldColumnOpacityInAnimation()
361 {
362     if (oldColumnOpacityInAnimation_) {
363         AnimationUtils::StopAnimation(oldColumnOpacityInAnimation_);
364     }
365 }
366 
StopOldColumnOpacityOutAnimation()367 void DateTimeAnimationController::StopOldColumnOpacityOutAnimation()
368 {
369     if (oldColumnOpacityOutAnimation_) {
370         AnimationUtils::StopAnimation(oldColumnOpacityOutAnimation_);
371     }
372 }
373 
PlayInAnimation()374 void DateTimeAnimationController::PlayInAnimation()
375 {
376     isInAnimationPlaying_ = true;
377     PlayTitleInAnimation();
378     PlayMovingInAnimation();
379 
380     StopOldColumnOpacityOutAnimation();
381     PlayOldColumnOpacityInAnimation();
382     PlayNewColumnOpacityInAnimation();
383     PlayYearColumnOpacityInAnimation();
384     PlayButtonOpacityInAnimation();
385 }
386 
PlayOutAnimation()387 void DateTimeAnimationController::PlayOutAnimation()
388 {
389     isOutAnimationPlaying_ = true;
390     PlayTitleOutAnimation();
391     PlayMovingOutAnimation();
392 
393     StopOldColumnOpacityInAnimation();
394     PlayOldColumnOpacityOutAnimation();
395     PlayNewColumnOpacityOutAnimation();
396     PlayYearColumnOpacityOutAnimation();
397     PlayButtonOpacityOutAnimation();
398 }
399 
400 
InitMoveRange()401 void DateTimeAnimationController::InitMoveRange()
402 {
403     yearEnd_ = 0.0;
404     monthEnd_ = 0.0;
405     dayEnd_ = 0.0;
406 
407     auto year = year_.Upgrade();
408     CHECK_NULL_VOID(year);
409     auto yearGeometry = year->GetGeometryNode();
410     CHECK_NULL_VOID(yearGeometry);
411     auto month = month_.Upgrade();
412     CHECK_NULL_VOID(month);
413     auto monthGeometry = month->GetGeometryNode();
414     CHECK_NULL_VOID(monthGeometry);
415     yearStart_ = 0;
416     monthStart_ = 0 - yearGeometry->GetFrameSize().Width();
417     dayStart_ = monthStart_ - monthGeometry->GetFrameSize().Width();
418 }
419 
420 
SetDatePicker(const RefPtr<FrameNode> & value)421 void DateTimeAnimationController::SetDatePicker(const RefPtr<FrameNode>& value)
422 {
423     datePicker_ = value;
424     auto children = value->GetChildren();
425     if (children.size() != CHILD_SIZE) {
426         return;
427     }
428     auto iter = children.begin();
429     auto year = (*iter);
430     CHECK_NULL_VOID(year);
431     iter++;
432     auto month = *iter;
433     CHECK_NULL_VOID(month);
434     iter++;
435     auto day = *iter;
436     CHECK_NULL_VOID(day);
437     year_ = DynamicCast<FrameNode>(year);
438     month_ = DynamicCast<FrameNode>(month);
439     day_ = DynamicCast<FrameNode>(day);
440 }
441 
Play(bool isIn)442 void DateTimeAnimationController::Play(bool isIn)
443 {
444     if (!created_) {
445         InitMoveRange();
446         created_ = true;
447     }
448 
449     if (isIn) {
450         PlayInAnimation();
451     } else {
452         PlayOutAnimation();
453     }
454 }
455 } // namespace OHOS::Ace
456