• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_ng/pattern/texttimer/text_timer_pattern.h"
17 
18 #include <stack>
19 #include <string>
20 
21 #include "base/i18n/localization.h"
22 #include "base/utils/utils.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components_ng/property/property.h"
25 
26 namespace OHOS::Ace::NG {
27 namespace {
28 constexpr double DEFAULT_COUNT = 60000.0;
29 const std::string DEFAULT_FORMAT = "HH:mm:ss.SS";
30 } // namespace
31 
TextTimerPattern()32 TextTimerPattern::TextTimerPattern()
33 {
34     textTimerController_ = MakeRefPtr<TextTimerController>();
35 }
36 
FireChangeEvent() const37 void TextTimerPattern::FireChangeEvent() const
38 {
39     auto textTimerEventHub = GetEventHub<TextTimerEventHub>();
40     CHECK_NULL_VOID(textTimerEventHub);
41     textTimerEventHub->FireChangeEvent(std::to_string(GetMilliseconds()), std::to_string(elapsedTime_));
42 }
43 
InitTextTimerController()44 void TextTimerPattern::InitTextTimerController()
45 {
46     if (textTimerController_) {
47         if (textTimerController_->HasInitialized()) {
48             return;
49         }
50         auto weak = AceType::WeakClaim(this);
51         textTimerController_->OnStart([weak]() {
52             auto timerRender = weak.Upgrade();
53             if (timerRender) {
54                 timerRender->HandleStart();
55             }
56         });
57         textTimerController_->OnPause([weak]() {
58             auto timerRender = weak.Upgrade();
59             if (timerRender) {
60                 timerRender->HandlePause();
61             }
62         });
63         textTimerController_->OnReset([weak]() {
64             auto timerRender = weak.Upgrade();
65             if (timerRender) {
66                 timerRender->HandleReset();
67             }
68         });
69     }
70 }
71 
InitTimerDisplay()72 void TextTimerPattern::InitTimerDisplay()
73 {
74     auto host = GetHost();
75     CHECK_NULL_VOID(host);
76 
77     auto weak = AceType::WeakClaim(this);
78     if (!scheduler_) {
79         auto&& callback = [weak](uint64_t duration) {
80             auto timer = weak.Upgrade();
81             if (timer) {
82                 timer->Tick(duration);
83             } else {
84                 LOGW("empty timer, skip tick callback.");
85             }
86         };
87         scheduler_ = SchedulerBuilder::Build(callback, host->GetContext());
88         auto count = isCountDown_ ? inputCount_ : 0;
89         UpdateTextTimer(static_cast<uint32_t>(count));
90     } else {
91         HandleReset();
92     }
93 }
94 
Tick(uint64_t duration)95 void TextTimerPattern::Tick(uint64_t duration)
96 {
97     elapsedTime_ += duration;
98     FireChangeEvent();
99 
100     auto tmpValue = static_cast<double>(elapsedTime_);
101     if (isCountDown_) {
102         tmpValue =
103             (inputCount_ >= static_cast<double>(elapsedTime_)) ? (inputCount_ - static_cast<double>(elapsedTime_)) : 0;
104     }
105     if (isCountDown_ && tmpValue <= 0) {
106         UpdateTextTimer(0);
107         HandlePause();
108         return;
109     }
110 
111     UpdateTextTimer(static_cast<uint32_t>(tmpValue));
112 }
113 
OnModifyDone()114 void TextTimerPattern::OnModifyDone()
115 {
116     auto host = GetHost();
117     CHECK_NULL_VOID(host);
118     auto textLayoutProperty = GetLayoutProperty<TextLayoutProperty>();
119     CHECK_NULL_VOID(textLayoutProperty);
120     textLayoutProperty->UpdateTextOverflow(TextOverflow::NONE);
121     if (textLayoutProperty->GetPositionProperty()) {
122         textLayoutProperty->UpdateAlignment(
123             textLayoutProperty->GetPositionProperty()->GetAlignment().value_or(Alignment::CENTER));
124     } else {
125         textLayoutProperty->UpdateAlignment(Alignment::CENTER);
126     }
127     textLayoutProperty->UpdateTextOverflow(TextOverflow::NONE);
128 
129     isCountDown_ = GetIsCountDown();
130     inputCount_ = GetInputCount();
131 
132     InitTextTimerController();
133     InitTimerDisplay();
134 }
135 
UpdateTextTimer(uint32_t elapsedTime)136 void TextTimerPattern::UpdateTextTimer(uint32_t elapsedTime)
137 {
138     auto host = GetHost();
139     CHECK_NULL_VOID(host);
140     auto textLayoutProperty = GetLayoutProperty<TextLayoutProperty>();
141     CHECK_NULL_VOID(textLayoutProperty);
142 
143     // format time text.
144     std::string timerText = Localization::GetInstance()->FormatDuration(elapsedTime, GetFormat());
145     if (timerText.empty()) {
146         timerText = Localization::GetInstance()->FormatDuration(elapsedTime, DEFAULT_FORMAT);
147     }
148     if (textLayoutProperty->GetContent() == timerText) {
149         return; // needless to update
150     }
151 
152     textLayoutProperty->UpdateContent(timerText); // Update time text.
153     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
154     TextPattern::OnModifyDone();
155 }
156 
GetFormat() const157 std::string TextTimerPattern::GetFormat() const
158 {
159     auto textTimerLayoutProperty = GetLayoutProperty<TextTimerLayoutProperty>();
160     CHECK_NULL_RETURN(textTimerLayoutProperty, DEFAULT_FORMAT);
161     return textTimerLayoutProperty->GetFormat().value_or(DEFAULT_FORMAT);
162 }
163 
GetIsCountDown() const164 bool TextTimerPattern::GetIsCountDown() const
165 {
166     auto textTimerLayoutProperty = GetLayoutProperty<TextTimerLayoutProperty>();
167     CHECK_NULL_RETURN(textTimerLayoutProperty, false);
168     return textTimerLayoutProperty->GetIsCountDown().value_or(false);
169 }
170 
GetInputCount() const171 double TextTimerPattern::GetInputCount() const
172 {
173     auto textTimerLayoutProperty = GetLayoutProperty<TextTimerLayoutProperty>();
174     CHECK_NULL_RETURN(textTimerLayoutProperty, DEFAULT_COUNT);
175     return textTimerLayoutProperty->GetInputCount().value_or(DEFAULT_COUNT);
176 }
177 
HandleStart()178 void TextTimerPattern::HandleStart()
179 {
180     if (scheduler_ && !scheduler_->IsActive()) {
181         scheduler_->Start();
182     }
183 }
184 
HandlePause()185 void TextTimerPattern::HandlePause()
186 {
187     if (scheduler_ && scheduler_->IsActive()) {
188         scheduler_->Stop();
189     }
190 }
191 
HandleReset()192 void TextTimerPattern::HandleReset()
193 {
194     if (scheduler_ && scheduler_->IsActive()) {
195         scheduler_->Stop();
196     }
197     elapsedTime_ = 0;
198     auto count = isCountDown_ ? inputCount_ : 0;
199     UpdateTextTimer(static_cast<uint32_t>(count));
200 }
201 } // namespace OHOS::Ace::NG
202