~aleteoryx/muditaos

ref: 3ff04e06c9eab6de2c9a2ded0876bed2d87eab93 muditaos/module-apps/apps-common/widgets/TimeMinuteSecondWidget.cpp -rw-r--r-- 6.0 KiB
3ff04e06 — Maciej Gibowicz [BH-1944] Changing the rounding method for minutes in relaxation 1 year, 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TimeMinuteSecondWidget.hpp"
#include <LanguageUtils.hpp>

namespace
{
    std::vector<std::uint32_t> valueToDigits(std::uint32_t value)
    {
        std::vector<std::uint32_t> digits;
        while (value) {
            digits.push_back(value % 10);
            value /= 10;
        }
        std::reverse(digits.begin(), digits.end());
        return digits;
    }

    std::uint32_t getRoundedMinutes(std::uint32_t currentSeconds, std::uint32_t totalSeconds)
    {
        constexpr auto halfMinute{utils::time::secondsInMinute / 2};
        const auto totalMin   = totalSeconds / utils::time::secondsInMinute;
        const auto totalSec   = totalSeconds % utils::time::secondsInMinute;
        const auto currentMin = currentSeconds / utils::time::secondsInMinute;

        // only at startup, when the number of seconds is less than 30, we round down
        if (totalMin > 0 && totalMin == currentMin && totalSec < halfMinute) {
            return currentMin;
        }
        // otherwise, we round up
        return currentMin + 1;
    }

    namespace digit
    {
        constexpr auto width      = 340U;
        constexpr auto height     = 95U;
        constexpr auto topMargin  = 30U;
        constexpr auto digitWidth = 48U;
        constexpr auto font       = style::window::font::supersizeme;
    } // namespace digit

    namespace description
    {
        constexpr auto width     = 226U;
        constexpr auto height    = 33U;
        constexpr auto topMargin = -2;
        constexpr auto font      = style::window::font::big;
    } // namespace description
} // namespace

namespace gui
{
    TimeMinuteSecondWidget::TimeMinuteSecondWidget(Item *parent,
                                                   const std::uint32_t &x,
                                                   const std::uint32_t &y,
                                                   const std::uint32_t &w,
                                                   const std::uint32_t &h,
                                                   DisplayType type)
        : Rect(parent, x, y, w, h), displayType{type}
    {
        buildInterface(w, h);
    }

    void TimeMinuteSecondWidget::buildInterface(const std::uint32_t w, const std::uint32_t h)
    {
        setEdges(gui::RectangleEdge::None);
        mainBox = new gui::VBox(this, 0, 0, w, h);
        mainBox->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
        mainBox->setEdges(gui::RectangleEdge::None);
        mainBox->activeItem = false;

        digitsContainer = new gui::HBox(mainBox, 0, 0, digit::width, digit::height);
        digitsContainer->setAlignment(
            gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        digitsContainer->setEdges(gui::RectangleEdge::None);
        digitsContainer->setMargins(gui::Margins(0, digit::topMargin, 0, 0));

        for (auto i = 0U; i < maxDigits; i++) {
            digitBox[i] = new gui::VBox(digitsContainer, 0, 0, digit::digitWidth, digit::height);
            digitBox[i]->setAlignment(
                gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            digitBox[i]->setEdges(gui::RectangleEdge::None);
            digitBox[i]->setMargins(gui::Margins(0, 0, 0, 0));

            digitsText[i] = new gui::Label(digitBox[i], 0, 0, 0, 0);
            digitsText[i]->setEdges(gui::RectangleEdge::None);
            digitsText[i]->setMaximumSize(digit::width, digit::height);
            digitsText[i]->setMargins(gui::Margins(0, 0, 0, 0));
            digitsText[i]->setAlignment(
                gui::Alignment{gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center});
            digitsText[i]->setFont(digit::font);

            digitBox[i]->resizeItems();
        }
        digitsContainer->resizeItems();

        descriptionBox = new gui::HBox(mainBox, 0, 0, description::width, description::height);
        descriptionBox->setAlignment(
            gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        descriptionBox->setEdges(gui::RectangleEdge::None);
        descriptionBox->setMargins(gui::Margins(0, description::topMargin, 0, 0));

        description = new gui::Label(descriptionBox, 0, 0, 0, 0);
        description->setEdges(gui::RectangleEdge::None);
        description->setMaximumSize(description::width, description::height);
        description->setMargins(gui::Margins(0, 0, 0, 0));
        description->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center});
        description->setFont(description::font);

        descriptionBox->resizeItems();
        mainBox->resizeItems();
    }

    void TimeMinuteSecondWidget::updateTime(std::uint32_t seconds)
    {
        if (!totalSeconds.has_value()) {
            totalSeconds = seconds;
        }
        if (displayType != DisplayType::OnlySeconds &&
            (seconds >= utils::time::secondsInMinute || displayType == DisplayType::OnlyMinutes)) {
            const auto minutes = getRoundedMinutes(seconds, totalSeconds.value());
            setText(minutes);
            description->setText(utils::language::getCorrectMinutesNumeralForm(minutes));
        }
        else {
            setText(seconds);
            description->setText(utils::language::getCorrectSecondsNumeralForm(seconds));
        }
    }

    void TimeMinuteSecondWidget::setText(std::uint32_t value)
    {
        const auto &digits     = valueToDigits(value);
        const auto totalDigits = digits.size();

        for (auto i = 0U; i < maxDigits; i++) {
            if (i < totalDigits) {
                digitsText[i]->setText(std::to_string(digits[i]));
                digitBox[i]->setVisible(true);
            }
            else {
                digitBox[i]->setVisible(false);
            }
        }
        digitsContainer->resizeItems();
    }
} /* namespace gui */