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_digital_clock.h"
17 #include <cstdio>
18 #include "components/ui_view_group.h"
19 #include "font/ui_font.h"
20 #include "gfx_utils/graphic_log.h"
21 #include "securec.h"
22 
23 namespace OHOS {
UIDigitalClock()24 UIDigitalClock::UIDigitalClock()
25     : timeLabels_{0},
26       displayMode_(DISPLAY_24_HOUR),
27       leadingZero_(true),
28       color_(Color::White()),
29       prevHour_(0),
30       prevMinute_(0),
31       prevSecond_(0),
32       verticalShow_(false)
33 {
34     style_ = &(StyleDefault::GetBackgroundTransparentStyle());
35 }
36 
InitTimeLabels()37 void UIDigitalClock::InitTimeLabels()
38 {
39     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
40         if (timeLabels_[i] == nullptr) {
41             timeLabels_[i] = new UILabel;
42             if (timeLabels_[i] == nullptr) {
43                 GRAPHIC_LOGE("new UILabel fail");
44                 return;
45             }
46             timeLabels_[i]->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
47             timeLabels_[i]->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
48             Add(timeLabels_[i]);
49         }
50     }
51 }
52 
DisplayLeadingZero(bool displayLeadingZero)53 void UIDigitalClock::DisplayLeadingZero(bool displayLeadingZero)
54 {
55     leadingZero_ = displayLeadingZero;
56     UpdateClock(false);
57 }
58 
SetOpacity(uint8_t opacity)59 void UIDigitalClock::SetOpacity(uint8_t opacity)
60 {
61     opaScale_ = opacity;
62     InitTimeLabels();
63     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
64         timeLabels_[i]->SetStyle(STYLE_TEXT_OPA, opacity);
65     }
66     RefreshTime();
67 }
68 
GetOpacity() const69 uint8_t UIDigitalClock::GetOpacity() const
70 {
71     return opaScale_;
72 }
73 
SetFontId(uint16_t fontId)74 void UIDigitalClock::SetFontId(uint16_t fontId)
75 {
76     SetStyle(STYLE_TEXT_FONT, fontId);
77     InitTimeLabels();
78     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
79         timeLabels_[i]->SetFontId(fontId);
80     }
81     UpdateClock(false);
82 }
83 
SetFont(const char * name,uint8_t size)84 void UIDigitalClock::SetFont(const char* name, uint8_t size)
85 {
86     InitTimeLabels();
87     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
88         timeLabels_[i]->SetFont(name, size);
89     }
90     UpdateClock(false);
91 }
92 
SetColor(ColorType color)93 void UIDigitalClock::SetColor(ColorType color)
94 {
95     color_ = color;
96     InitTimeLabels();
97     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
98         timeLabels_[i]->SetStyle(STYLE_TEXT_COLOR, color.full);
99     }
100     RefreshTime();
101 }
102 
TimeElementRefresh()103 void UIDigitalClock::TimeElementRefresh()
104 {
105     InitTimeLabels();
106     if (currentHour_ != prevHour_) {
107         prevHour_ = currentHour_;
108         timeLabels_[HOUR_ELEMENT]->Invalidate();
109     }
110 
111     if (currentMinute_ != prevMinute_) {
112         prevMinute_ = currentMinute_;
113         timeLabels_[MINUTE_ELEMENT]->Invalidate();
114     }
115 
116     if (currentSecond_ != prevSecond_) {
117         prevSecond_ = currentSecond_;
118         timeLabels_[SECOND_ELEMENT]->Invalidate();
119     }
120 }
121 
RefreshTime()122 void UIDigitalClock::RefreshTime()
123 {
124     InitTimeLabels();
125     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
126         timeLabels_[i]->Invalidate();
127     }
128 }
129 
UpdateClock(bool clockInit)130 void UIDigitalClock::UpdateClock(bool clockInit)
131 {
132     char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE] = {{0}};
133     const char* formatWithColon = leadingZero_ ? "%02d:" : "%d:";
134     const char* formatWithoutColon = leadingZero_ ? "%02d" : "%d";
135     const char* format = verticalShow_ ? formatWithoutColon : formatWithColon;
136     const char* formatForMinute = verticalShow_ ? "%02d" : "%02d:";
137     switch (displayMode_) {
138         case DISPLAY_24_HOUR_NO_SECONDS: {
139             if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
140                 return;
141             }
142             if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
143                 return;
144             }
145             break;
146         }
147         case DISPLAY_12_HOUR_NO_SECONDS: {
148             if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
149                 return;
150             }
151             if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
152                 return;
153             }
154             break;
155         }
156         case DISPLAY_12_HOUR: {
157             if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
158                 return;
159             }
160             if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
161                 return;
162             }
163             if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
164                 return;
165             }
166             break;
167         }
168         case DISPLAY_24_HOUR: {
169             if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
170                 return;
171             }
172             if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
173                 return;
174             }
175             if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
176                 return;
177             }
178             break;
179         }
180         default: {
181             break;
182         }
183     }
184     SetTimeLabels(buf);
185 }
186 
SetTimeLabels(const char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE])187 void UIDigitalClock::SetTimeLabels(const char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE])
188 {
189     InitTimeLabels();
190     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
191         timeLabels_[i]->SetText(buf[i]);
192     }
193 
194     SetTimeLabelsPosition();
195     TimeElementRefresh();
196 }
197 
SetHorizontal()198 void UIDigitalClock::SetHorizontal()
199 {
200     InitTimeLabels();
201     uint16_t totalWidth = timeLabels_[HOUR_ELEMENT]->GetWidth() + timeLabels_[MINUTE_ELEMENT]->GetWidth() +
202                           timeLabels_[SECOND_ELEMENT]->GetWidth();
203     UITextLanguageAlignment align = timeLabels_[HOUR_ELEMENT]->GetHorAlign();
204     int16_t x = 0;
205     Rect rect = GetContentRect();
206     if (align == TEXT_ALIGNMENT_CENTER) {
207         x = (rect.GetWidth() >> 1) - (totalWidth >> 1);
208     } else if (align == TEXT_ALIGNMENT_RIGHT) {
209         x = rect.GetRight() - totalWidth;
210     }
211     timeLabels_[HOUR_ELEMENT]->SetPosition(x, 0);
212     int16_t width = timeLabels_[HOUR_ELEMENT]->GetWidth();
213     for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
214         timeLabels_[i]->SetPosition(x + width, 0);
215         width += timeLabels_[i]->GetWidth();
216     }
217 }
218 
SetTimeLabelsPosition()219 void UIDigitalClock::SetTimeLabelsPosition()
220 {
221     if (verticalShow_) {
222         SetVertical();
223     } else {
224         SetHorizontal();
225     }
226 }
227 
SetVertical()228 void UIDigitalClock::SetVertical()
229 {
230     InitTimeLabels();
231     int16_t fontHeight = timeLabels_[HOUR_ELEMENT]->GetHeight();
232     timeLabels_[HOUR_ELEMENT]->SetPosition(0, 0);
233     int16_t y = fontHeight;
234     for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
235         timeLabels_[i]->SetPosition(0, y);
236         y += fontHeight;
237     }
238 }
239 
~UIDigitalClock()240 UIDigitalClock::~UIDigitalClock()
241 {
242     for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
243         if (timeLabels_[i] != nullptr) {
244             Remove(timeLabels_[i]);
245             delete timeLabels_[i];
246             timeLabels_[i] = nullptr;
247         }
248     }
249 }
250 } // namespace OHOS
251