1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "components/ui_digital_clock.h"
17a3e0fd82Sopenharmony_ci#include <cstdio>
18a3e0fd82Sopenharmony_ci#include "components/ui_view_group.h"
19a3e0fd82Sopenharmony_ci#include "font/ui_font.h"
20a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
21a3e0fd82Sopenharmony_ci#include "securec.h"
22a3e0fd82Sopenharmony_ci
23a3e0fd82Sopenharmony_cinamespace OHOS {
24a3e0fd82Sopenharmony_ciUIDigitalClock::UIDigitalClock()
25a3e0fd82Sopenharmony_ci    : timeLabels_{0},
26a3e0fd82Sopenharmony_ci      displayMode_(DISPLAY_24_HOUR),
27a3e0fd82Sopenharmony_ci      leadingZero_(true),
28a3e0fd82Sopenharmony_ci      color_(Color::White()),
29a3e0fd82Sopenharmony_ci      prevHour_(0),
30a3e0fd82Sopenharmony_ci      prevMinute_(0),
31a3e0fd82Sopenharmony_ci      prevSecond_(0),
32a3e0fd82Sopenharmony_ci      verticalShow_(false)
33a3e0fd82Sopenharmony_ci{
34a3e0fd82Sopenharmony_ci    style_ = &(StyleDefault::GetBackgroundTransparentStyle());
35a3e0fd82Sopenharmony_ci}
36a3e0fd82Sopenharmony_ci
37a3e0fd82Sopenharmony_civoid UIDigitalClock::InitTimeLabels()
38a3e0fd82Sopenharmony_ci{
39a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
40a3e0fd82Sopenharmony_ci        if (timeLabels_[i] == nullptr) {
41a3e0fd82Sopenharmony_ci            timeLabels_[i] = new UILabel;
42a3e0fd82Sopenharmony_ci            if (timeLabels_[i] == nullptr) {
43a3e0fd82Sopenharmony_ci                GRAPHIC_LOGE("new UILabel fail");
44a3e0fd82Sopenharmony_ci                return;
45a3e0fd82Sopenharmony_ci            }
46a3e0fd82Sopenharmony_ci            timeLabels_[i]->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
47a3e0fd82Sopenharmony_ci            timeLabels_[i]->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
48a3e0fd82Sopenharmony_ci            Add(timeLabels_[i]);
49a3e0fd82Sopenharmony_ci        }
50a3e0fd82Sopenharmony_ci    }
51a3e0fd82Sopenharmony_ci}
52a3e0fd82Sopenharmony_ci
53a3e0fd82Sopenharmony_civoid UIDigitalClock::DisplayLeadingZero(bool displayLeadingZero)
54a3e0fd82Sopenharmony_ci{
55a3e0fd82Sopenharmony_ci    leadingZero_ = displayLeadingZero;
56a3e0fd82Sopenharmony_ci    UpdateClock(false);
57a3e0fd82Sopenharmony_ci}
58a3e0fd82Sopenharmony_ci
59a3e0fd82Sopenharmony_civoid UIDigitalClock::SetOpacity(uint8_t opacity)
60a3e0fd82Sopenharmony_ci{
61a3e0fd82Sopenharmony_ci    opaScale_ = opacity;
62a3e0fd82Sopenharmony_ci    InitTimeLabels();
63a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
64a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetStyle(STYLE_TEXT_OPA, opacity);
65a3e0fd82Sopenharmony_ci    }
66a3e0fd82Sopenharmony_ci    RefreshTime();
67a3e0fd82Sopenharmony_ci}
68a3e0fd82Sopenharmony_ci
69a3e0fd82Sopenharmony_ciuint8_t UIDigitalClock::GetOpacity() const
70a3e0fd82Sopenharmony_ci{
71a3e0fd82Sopenharmony_ci    return opaScale_;
72a3e0fd82Sopenharmony_ci}
73a3e0fd82Sopenharmony_ci
74a3e0fd82Sopenharmony_civoid UIDigitalClock::SetFontId(uint16_t fontId)
75a3e0fd82Sopenharmony_ci{
76a3e0fd82Sopenharmony_ci    SetStyle(STYLE_TEXT_FONT, fontId);
77a3e0fd82Sopenharmony_ci    InitTimeLabels();
78a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
79a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetFontId(fontId);
80a3e0fd82Sopenharmony_ci    }
81a3e0fd82Sopenharmony_ci    UpdateClock(false);
82a3e0fd82Sopenharmony_ci}
83a3e0fd82Sopenharmony_ci
84a3e0fd82Sopenharmony_civoid UIDigitalClock::SetFont(const char* name, uint8_t size)
85a3e0fd82Sopenharmony_ci{
86a3e0fd82Sopenharmony_ci    InitTimeLabels();
87a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
88a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetFont(name, size);
89a3e0fd82Sopenharmony_ci    }
90a3e0fd82Sopenharmony_ci    UpdateClock(false);
91a3e0fd82Sopenharmony_ci}
92a3e0fd82Sopenharmony_ci
93a3e0fd82Sopenharmony_civoid UIDigitalClock::SetColor(ColorType color)
94a3e0fd82Sopenharmony_ci{
95a3e0fd82Sopenharmony_ci    color_ = color;
96a3e0fd82Sopenharmony_ci    InitTimeLabels();
97a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
98a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetStyle(STYLE_TEXT_COLOR, color.full);
99a3e0fd82Sopenharmony_ci    }
100a3e0fd82Sopenharmony_ci    RefreshTime();
101a3e0fd82Sopenharmony_ci}
102a3e0fd82Sopenharmony_ci
103a3e0fd82Sopenharmony_civoid UIDigitalClock::TimeElementRefresh()
104a3e0fd82Sopenharmony_ci{
105a3e0fd82Sopenharmony_ci    InitTimeLabels();
106a3e0fd82Sopenharmony_ci    if (currentHour_ != prevHour_) {
107a3e0fd82Sopenharmony_ci        prevHour_ = currentHour_;
108a3e0fd82Sopenharmony_ci        timeLabels_[HOUR_ELEMENT]->Invalidate();
109a3e0fd82Sopenharmony_ci    }
110a3e0fd82Sopenharmony_ci
111a3e0fd82Sopenharmony_ci    if (currentMinute_ != prevMinute_) {
112a3e0fd82Sopenharmony_ci        prevMinute_ = currentMinute_;
113a3e0fd82Sopenharmony_ci        timeLabels_[MINUTE_ELEMENT]->Invalidate();
114a3e0fd82Sopenharmony_ci    }
115a3e0fd82Sopenharmony_ci
116a3e0fd82Sopenharmony_ci    if (currentSecond_ != prevSecond_) {
117a3e0fd82Sopenharmony_ci        prevSecond_ = currentSecond_;
118a3e0fd82Sopenharmony_ci        timeLabels_[SECOND_ELEMENT]->Invalidate();
119a3e0fd82Sopenharmony_ci    }
120a3e0fd82Sopenharmony_ci}
121a3e0fd82Sopenharmony_ci
122a3e0fd82Sopenharmony_civoid UIDigitalClock::RefreshTime()
123a3e0fd82Sopenharmony_ci{
124a3e0fd82Sopenharmony_ci    InitTimeLabels();
125a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
126a3e0fd82Sopenharmony_ci        timeLabels_[i]->Invalidate();
127a3e0fd82Sopenharmony_ci    }
128a3e0fd82Sopenharmony_ci}
129a3e0fd82Sopenharmony_ci
130a3e0fd82Sopenharmony_civoid UIDigitalClock::UpdateClock(bool clockInit)
131a3e0fd82Sopenharmony_ci{
132a3e0fd82Sopenharmony_ci    char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE] = {{0}};
133a3e0fd82Sopenharmony_ci    const char* formatWithColon = leadingZero_ ? "%02d:" : "%d:";
134a3e0fd82Sopenharmony_ci    const char* formatWithoutColon = leadingZero_ ? "%02d" : "%d";
135a3e0fd82Sopenharmony_ci    const char* format = verticalShow_ ? formatWithoutColon : formatWithColon;
136a3e0fd82Sopenharmony_ci    const char* formatForMinute = verticalShow_ ? "%02d" : "%02d:";
137a3e0fd82Sopenharmony_ci    switch (displayMode_) {
138a3e0fd82Sopenharmony_ci        case DISPLAY_24_HOUR_NO_SECONDS: {
139a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
140a3e0fd82Sopenharmony_ci                return;
141a3e0fd82Sopenharmony_ci            }
142a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
143a3e0fd82Sopenharmony_ci                return;
144a3e0fd82Sopenharmony_ci            }
145a3e0fd82Sopenharmony_ci            break;
146a3e0fd82Sopenharmony_ci        }
147a3e0fd82Sopenharmony_ci        case DISPLAY_12_HOUR_NO_SECONDS: {
148a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
149a3e0fd82Sopenharmony_ci                return;
150a3e0fd82Sopenharmony_ci            }
151a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
152a3e0fd82Sopenharmony_ci                return;
153a3e0fd82Sopenharmony_ci            }
154a3e0fd82Sopenharmony_ci            break;
155a3e0fd82Sopenharmony_ci        }
156a3e0fd82Sopenharmony_ci        case DISPLAY_12_HOUR: {
157a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
158a3e0fd82Sopenharmony_ci                return;
159a3e0fd82Sopenharmony_ci            }
160a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
161a3e0fd82Sopenharmony_ci                return;
162a3e0fd82Sopenharmony_ci            }
163a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
164a3e0fd82Sopenharmony_ci                return;
165a3e0fd82Sopenharmony_ci            }
166a3e0fd82Sopenharmony_ci            break;
167a3e0fd82Sopenharmony_ci        }
168a3e0fd82Sopenharmony_ci        case DISPLAY_24_HOUR: {
169a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
170a3e0fd82Sopenharmony_ci                return;
171a3e0fd82Sopenharmony_ci            }
172a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
173a3e0fd82Sopenharmony_ci                return;
174a3e0fd82Sopenharmony_ci            }
175a3e0fd82Sopenharmony_ci            if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
176a3e0fd82Sopenharmony_ci                return;
177a3e0fd82Sopenharmony_ci            }
178a3e0fd82Sopenharmony_ci            break;
179a3e0fd82Sopenharmony_ci        }
180a3e0fd82Sopenharmony_ci        default: {
181a3e0fd82Sopenharmony_ci            break;
182a3e0fd82Sopenharmony_ci        }
183a3e0fd82Sopenharmony_ci    }
184a3e0fd82Sopenharmony_ci    SetTimeLabels(buf);
185a3e0fd82Sopenharmony_ci}
186a3e0fd82Sopenharmony_ci
187a3e0fd82Sopenharmony_civoid UIDigitalClock::SetTimeLabels(const char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE])
188a3e0fd82Sopenharmony_ci{
189a3e0fd82Sopenharmony_ci    InitTimeLabels();
190a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
191a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetText(buf[i]);
192a3e0fd82Sopenharmony_ci    }
193a3e0fd82Sopenharmony_ci
194a3e0fd82Sopenharmony_ci    SetTimeLabelsPosition();
195a3e0fd82Sopenharmony_ci    TimeElementRefresh();
196a3e0fd82Sopenharmony_ci}
197a3e0fd82Sopenharmony_ci
198a3e0fd82Sopenharmony_civoid UIDigitalClock::SetHorizontal()
199a3e0fd82Sopenharmony_ci{
200a3e0fd82Sopenharmony_ci    InitTimeLabels();
201a3e0fd82Sopenharmony_ci    uint16_t totalWidth = timeLabels_[HOUR_ELEMENT]->GetWidth() + timeLabels_[MINUTE_ELEMENT]->GetWidth() +
202a3e0fd82Sopenharmony_ci                          timeLabels_[SECOND_ELEMENT]->GetWidth();
203a3e0fd82Sopenharmony_ci    UITextLanguageAlignment align = timeLabels_[HOUR_ELEMENT]->GetHorAlign();
204a3e0fd82Sopenharmony_ci    int16_t x = 0;
205a3e0fd82Sopenharmony_ci    Rect rect = GetContentRect();
206a3e0fd82Sopenharmony_ci    if (align == TEXT_ALIGNMENT_CENTER) {
207a3e0fd82Sopenharmony_ci        x = (rect.GetWidth() >> 1) - (totalWidth >> 1);
208a3e0fd82Sopenharmony_ci    } else if (align == TEXT_ALIGNMENT_RIGHT) {
209a3e0fd82Sopenharmony_ci        x = rect.GetRight() - totalWidth;
210a3e0fd82Sopenharmony_ci    }
211a3e0fd82Sopenharmony_ci    timeLabels_[HOUR_ELEMENT]->SetPosition(x, 0);
212a3e0fd82Sopenharmony_ci    int16_t width = timeLabels_[HOUR_ELEMENT]->GetWidth();
213a3e0fd82Sopenharmony_ci    for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
214a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetPosition(x + width, 0);
215a3e0fd82Sopenharmony_ci        width += timeLabels_[i]->GetWidth();
216a3e0fd82Sopenharmony_ci    }
217a3e0fd82Sopenharmony_ci}
218a3e0fd82Sopenharmony_ci
219a3e0fd82Sopenharmony_civoid UIDigitalClock::SetTimeLabelsPosition()
220a3e0fd82Sopenharmony_ci{
221a3e0fd82Sopenharmony_ci    if (verticalShow_) {
222a3e0fd82Sopenharmony_ci        SetVertical();
223a3e0fd82Sopenharmony_ci    } else {
224a3e0fd82Sopenharmony_ci        SetHorizontal();
225a3e0fd82Sopenharmony_ci    }
226a3e0fd82Sopenharmony_ci}
227a3e0fd82Sopenharmony_ci
228a3e0fd82Sopenharmony_civoid UIDigitalClock::SetVertical()
229a3e0fd82Sopenharmony_ci{
230a3e0fd82Sopenharmony_ci    InitTimeLabels();
231a3e0fd82Sopenharmony_ci    int16_t fontHeight = timeLabels_[HOUR_ELEMENT]->GetHeight();
232a3e0fd82Sopenharmony_ci    timeLabels_[HOUR_ELEMENT]->SetPosition(0, 0);
233a3e0fd82Sopenharmony_ci    int16_t y = fontHeight;
234a3e0fd82Sopenharmony_ci    for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
235a3e0fd82Sopenharmony_ci        timeLabels_[i]->SetPosition(0, y);
236a3e0fd82Sopenharmony_ci        y += fontHeight;
237a3e0fd82Sopenharmony_ci    }
238a3e0fd82Sopenharmony_ci}
239a3e0fd82Sopenharmony_ci
240a3e0fd82Sopenharmony_ciUIDigitalClock::~UIDigitalClock()
241a3e0fd82Sopenharmony_ci{
242a3e0fd82Sopenharmony_ci    for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
243a3e0fd82Sopenharmony_ci        if (timeLabels_[i] != nullptr) {
244a3e0fd82Sopenharmony_ci            Remove(timeLabels_[i]);
245a3e0fd82Sopenharmony_ci            delete timeLabels_[i];
246a3e0fd82Sopenharmony_ci            timeLabels_[i] = nullptr;
247a3e0fd82Sopenharmony_ci        }
248a3e0fd82Sopenharmony_ci    }
249a3e0fd82Sopenharmony_ci}
250a3e0fd82Sopenharmony_ci} // namespace OHOS
251