• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 "components/ui_label.h"
17 #include "font/ui_font.h"
18 #include "gfx_utils/graphic_log.h"
19 #include "themes/theme_manager.h"
20 
21 namespace OHOS {
22 class LabelAnimator : public Animator, public AnimatorCallback {
23 public:
LabelAnimator(uint16_t textX,uint16_t labelX,int16_t startPos,UIView * view)24     LabelAnimator(uint16_t textX, uint16_t labelX, int16_t startPos, UIView* view)
25         : Animator(this, view, 0, true),
26           startPos_(startPos),
27           textX_(textX),
28           labelX_(labelX),
29           offsetX_(startPos),
30           waitCount_(ANIM_WAIT_COUNT),
31           speed_(0),
32           preRunTime_(0),
33           decimal_(0)
34     {
35     }
36 
~LabelAnimator()37     virtual ~LabelAnimator() {}
38 
GetStartPos() const39     int16_t GetStartPos() const
40     {
41         return startPos_;
42     }
43 
SetStartPos(int16_t pos)44     void SetStartPos(int16_t pos)
45     {
46         startPos_ = pos;
47     }
48 
UpdateWidth(uint16_t textWidth,uint16_t labelWidth)49     void UpdateWidth(uint16_t textWidth, uint16_t labelWidth)
50     {
51         textX_ = textWidth;
52         labelX_ = labelWidth;
53         waitCount_ = ANIM_WAIT_COUNT;
54         preRunTime_ = 0;
55         decimal_ = 0;
56         offsetX_ = startPos_;
57         static_cast<UILabel*>(view_)->offsetX_ = offsetX_;
58         view_->Invalidate();
59     }
60 
Callback(UIView * view)61     void Callback(UIView* view) override
62     {
63         if (view == nullptr) {
64             return;
65         }
66 
67         uint32_t curTime = GetRunTime();
68         if (waitCount_ > 0) {
69             waitCount_--;
70             preRunTime_ = curTime;
71             return;
72         }
73         if (curTime == preRunTime_) {
74             return;
75         }
76         uint32_t time = (curTime > preRunTime_) ? (curTime - preRunTime_) : (UINT32_MAX - preRunTime_ + curTime);
77         // 1000: 1000 milliseconds is 1 second
78         float floatStep = (static_cast<float>(time * speed_) / 1000) + decimal_;
79         uint16_t integerStep = static_cast<uint16_t>(floatStep);
80         decimal_ = floatStep - integerStep;
81         preRunTime_ = curTime;
82 
83         if (integerStep != 0) {
84             offsetX_ -= integerStep;
85         } else {
86             return;
87         }
88         offsetX_ = ((offsetX_ - labelX_) % (textX_ + labelX_)) + labelX_;
89         static_cast<UILabel*>(view)->offsetX_ = offsetX_;
90         view->Invalidate();
91     }
92 
SetAnimatorSpeed(uint16_t animSpeed)93     void SetAnimatorSpeed(uint16_t animSpeed)
94     {
95         speed_ = animSpeed;
96         decimal_ = 0;
97     }
98 
99 private:
100     static constexpr uint8_t ANIM_WAIT_COUNT = 50;
101     int16_t startPos_;
102     uint16_t textX_;
103     uint16_t labelX_;
104     int16_t offsetX_;
105     uint16_t waitCount_;
106     uint16_t speed_;
107     uint32_t preRunTime_;
108     float decimal_;
109 };
110 
UILabel()111 UILabel::UILabel()
112     : labelText_(nullptr),
113       needRefresh_(false),
114       useTextColor_(false),
115       hasAnimator_(false),
116       lineBreakMode_(LINE_BREAK_ELLIPSIS),
117       ellipsisIndex_(Text::TEXT_ELLIPSIS_END_INV),
118       offsetX_(0),
119       textColor_(Color::White()),
120       animator_{nullptr}
121 {
122     Theme* theme = ThemeManager::GetInstance().GetCurrent();
123     Style& style = (theme != nullptr) ? (theme->GetLabelStyle()) : (StyleDefault::GetLabelStyle());
124     UIView::SetStyle(style);
125     animator_.speed = DEFAULT_ANIMATOR_SPEED;
126 }
127 
~UILabel()128 UILabel::~UILabel()
129 {
130     if (hasAnimator_) {
131         delete animator_.animator;
132         animator_.animator = nullptr;
133         hasAnimator_ = false;
134     }
135     if (labelText_ != nullptr) {
136         delete labelText_;
137         labelText_ = nullptr;
138     }
139 }
140 
InitLabelText()141 void UILabel::InitLabelText()
142 {
143     if (labelText_ == nullptr) {
144         labelText_ = new Text();
145     }
146 }
147 
GetWidth()148 int16_t UILabel::GetWidth()
149 {
150     InitLabelText();
151     if (needRefresh_ && labelText_->IsExpandWidth()) {
152         ReMeasure();
153     }
154     return UIView::GetWidth();
155 }
156 
GetHeight()157 int16_t UILabel::GetHeight()
158 {
159     InitLabelText();
160     if (needRefresh_ && labelText_->IsExpandHeight()) {
161         ReMeasure();
162     }
163     return UIView::GetHeight();
164 }
165 
SetStyle(uint8_t key,int64_t value)166 void UILabel::SetStyle(uint8_t key, int64_t value)
167 {
168     UIView::SetStyle(key, value);
169     RefreshLabel();
170 }
171 
SetText(const char * text)172 void UILabel::SetText(const char* text)
173 {
174     InitLabelText();
175     labelText_->SetText(text);
176     if (labelText_->IsNeedRefresh()) {
177         RefreshLabel();
178     }
179 }
180 
SetLineBreakMode(const uint8_t lineBreakMode)181 void UILabel::SetLineBreakMode(const uint8_t lineBreakMode)
182 {
183     InitLabelText();
184     if ((lineBreakMode >= LINE_BREAK_MAX) || (lineBreakMode_ == lineBreakMode)) {
185         return;
186     }
187     lineBreakMode_ = lineBreakMode;
188     if ((lineBreakMode_ == LINE_BREAK_ADAPT) || (lineBreakMode_ == LINE_BREAK_STRETCH) ||
189         (lineBreakMode_ == LINE_BREAK_MARQUEE)) {
190         labelText_->SetExpandWidth(true);
191     } else {
192         labelText_->SetExpandWidth(false);
193     }
194     if ((lineBreakMode_ == LINE_BREAK_ADAPT) || (lineBreakMode_ == LINE_BREAK_WRAP)) {
195         labelText_->SetExpandHeight(true);
196     } else {
197         labelText_->SetExpandHeight(false);
198     }
199     if (lineBreakMode_ != LINE_BREAK_MARQUEE) {
200         offsetX_ = 0;
201         if (hasAnimator_) {
202             animator_.animator->Stop();
203         }
204     }
205     RefreshLabel();
206 }
207 
SetAlign(UITextLanguageAlignment horizontalAlign,UITextLanguageAlignment verticalAlign)208 void UILabel::SetAlign(UITextLanguageAlignment horizontalAlign, UITextLanguageAlignment verticalAlign)
209 {
210     InitLabelText();
211     labelText_->SetAlign(horizontalAlign, verticalAlign);
212     if (labelText_->IsNeedRefresh()) {
213         RefreshLabel();
214     }
215 }
216 
SetFontId(uint8_t fontId)217 void UILabel::SetFontId(uint8_t fontId)
218 {
219     InitLabelText();
220     labelText_->SetFontId(fontId);
221     if (labelText_->IsNeedRefresh()) {
222         RefreshLabel();
223     }
224 }
225 
SetFont(const char * name,uint8_t size)226 void UILabel::SetFont(const char* name, uint8_t size)
227 {
228     InitLabelText();
229     labelText_->SetFont(name, size);
230     if (labelText_->IsNeedRefresh()) {
231         RefreshLabel();
232     }
233 }
234 
GetTextWidth()235 uint16_t UILabel::GetTextWidth()
236 {
237     InitLabelText();
238     if (labelText_->IsNeedRefresh()) {
239         ReMeasure();
240     }
241     return labelText_->GetTextSize().x;
242 }
243 
GetTextHeight()244 uint16_t UILabel::GetTextHeight()
245 {
246     InitLabelText();
247     if (labelText_->IsNeedRefresh()) {
248         ReMeasure();
249     }
250     return labelText_->GetTextSize().y;
251 }
252 
SetWidth(int16_t width)253 void UILabel::SetWidth(int16_t width)
254 {
255     if (GetWidth() != width) {
256         UIView::SetWidth(width);
257         RefreshLabel();
258     }
259 }
260 
SetHeight(int16_t height)261 void UILabel::SetHeight(int16_t height)
262 {
263     if (GetHeight() != height) {
264         UIView::SetHeight(height);
265         RefreshLabel();
266     }
267 }
268 
RefreshLabel()269 void UILabel::RefreshLabel()
270 {
271     Invalidate();
272     ellipsisIndex_ = Text::TEXT_ELLIPSIS_END_INV;
273     if (!needRefresh_) {
274         needRefresh_ = true;
275     }
276 }
277 
ReMeasure()278 void UILabel::ReMeasure()
279 {
280     if (!needRefresh_) {
281         return;
282     }
283     needRefresh_ = false;
284     InitLabelText();
285     Style style = GetStyleConst();
286     style.textColor_ = GetTextColor();
287     bool flag = false;
288     if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
289         transMap_->SetInvalid(true);
290         flag = true;
291     }
292     labelText_->ReMeasureTextSize(GetContentRect(), style);
293     Point textSize = labelText_->GetTextSize();
294     switch (lineBreakMode_) {
295         case LINE_BREAK_ADAPT:
296             Resize(textSize.x, textSize.y);
297             break;
298         case LINE_BREAK_STRETCH:
299             SetWidth(textSize.x);
300             break;
301         case LINE_BREAK_WRAP:
302             SetHeight(textSize.y);
303             break;
304         case LINE_BREAK_ELLIPSIS:
305             ellipsisIndex_ = labelText_->GetEllipsisIndex(GetContentRect(), style);
306             labelText_->ReMeasureTextWidthInEllipsisMode(GetContentRect(), style, ellipsisIndex_);
307             break;
308         case LINE_BREAK_MARQUEE:
309             RemeasureForMarquee(textSize.x);
310             break;
311         default:
312             break;
313     }
314     if ((transMap_ != nullptr) && flag) {
315         transMap_->SetInvalid(false);
316     }
317 }
318 
RemeasureForMarquee(int16_t textWidth)319 void UILabel::RemeasureForMarquee(int16_t textWidth)
320 {
321     int16_t rectWidth = GetWidth();
322     if (textWidth > rectWidth) {
323         offsetX_ = GetRollStartPos();
324         if (labelText_->GetDirect() == TEXT_DIRECT_RTL) {
325             labelText_->SetAlign(TEXT_ALIGNMENT_RIGHT);
326         } else {
327             labelText_->SetAlign(TEXT_ALIGNMENT_LEFT);
328         }
329         if (hasAnimator_) {
330             static_cast<LabelAnimator*>(animator_.animator)->UpdateWidth(textWidth, rectWidth);
331         } else {
332             LabelAnimator* animator = new LabelAnimator(textWidth, rectWidth, offsetX_, this);
333             if (animator == nullptr) {
334                 GRAPHIC_LOGE("new LabelAnimator fail");
335                 return;
336             }
337             animator->SetAnimatorSpeed(animator_.speed);
338             animator_.animator = animator;
339             hasAnimator_ = true;
340         }
341         animator_.animator->Start();
342     } else {
343         offsetX_ = 0;
344         if (hasAnimator_) {
345             animator_.animator->Stop();
346         }
347     }
348 }
349 
SetRollStartPos(int16_t pos)350 void UILabel::SetRollStartPos(int16_t pos)
351 {
352     if (hasAnimator_) {
353         static_cast<LabelAnimator*>(animator_.animator)->SetStartPos(pos);
354     } else {
355         animator_.pos = pos;
356     }
357 }
358 
GetRollStartPos() const359 int16_t UILabel::GetRollStartPos() const
360 {
361     return hasAnimator_ ? static_cast<LabelAnimator*>(animator_.animator)->GetStartPos() : animator_.pos;
362 }
363 
SetRollSpeed(uint16_t speed)364 void UILabel::SetRollSpeed(uint16_t speed)
365 {
366     if (hasAnimator_) {
367         static_cast<LabelAnimator*>(animator_.animator)->SetAnimatorSpeed(speed);
368     } else {
369         animator_.speed = speed;
370     }
371 }
372 
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea)373 void UILabel::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
374 {
375     InitLabelText();
376     UIView::OnDraw(gfxDstBuffer, invalidatedArea);
377     Style style = GetStyleConst();
378     style.textColor_ = GetTextColor();
379     OpacityType opa = GetMixOpaScale();
380     labelText_->OnDraw(gfxDstBuffer, invalidatedArea, GetOrigRect(),
381                        GetContentRect(), offsetX_, style, ellipsisIndex_, opa);
382 }
383 } // namespace OHOS