~aleteoryx/muditaos

1d19c549cfd4560766992949349cec9364623c86 — Maciej Janicki 3 years ago 83bbacf
[BH-1444] Fix vertical layout

Fix vertical layout:
- fix wrong hour displayed
- fix scrambled layout
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +2 -2
@@ 42,7 42,7 @@ target_sources(application-bell-common
        src/widgets/ProgressTimerWithSnoozeTimer.cpp
        src/widgets/SnoozeTimer.cpp
        src/widgets/LayoutVertical.cpp
        src/widgets/TimeSetSpinnerVertical.cpp
        src/widgets/ClockVertical.cpp

        src/options/BellOptionWindow.cpp
        src/options/BellShortOptionWindow.cpp


@@ 98,7 98,7 @@ target_sources(application-bell-common
        include/common/widgets/SnoozeTimer.hpp
        include/common/widgets/ListItems.hpp
        include/common/widgets/LayoutVertical.hpp
        include/common/widgets/TimeSetSpinnerVertical.hpp
        include/common/widgets/ClockVertical.hpp
        include/common/options/BellOptionWindow.hpp
        include/common/options/BellShortOptionWindow.hpp
        include/common/options/OptionBellMenu.hpp

M products/BellHybrid/apps/common/include/common/layouts/HomeScreenLayoutVertical.hpp => products/BellHybrid/apps/common/include/common/layouts/HomeScreenLayoutVertical.hpp +1 -1
@@ 16,7 16,7 @@ namespace gui
    class TextFixedSize;
    class AlarmIcon;
    class AlarmSetSpinner;
    class TimeSetSpinnerVertical;
    class ClockVertical;
    class TimeSetFmtSpinner;
    class SnoozeTimer;
    class BellBattery;

R products/BellHybrid/apps/common/include/common/widgets/TimeSetSpinnerVertical.hpp => products/BellHybrid/apps/common/include/common/widgets/ClockVertical.hpp +13 -25
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 16,10 16,6 @@ namespace style::time_set_spinner_vertical
    {
        inline constexpr auto size = 6U;
    } // namespace focus

    inline constexpr auto small_margin = 6U;
    inline constexpr auto big_margin   = 44U;
    inline constexpr auto colossal_margin = -40;
} // namespace style::time_set_spinner_vertical

namespace gui


@@ 32,16 28,15 @@ namespace gui
    /// Two time formats are supported:
    /// utils::time::Locale::TimeFormat::FormatTime12H
    /// utils::time::Locale::TimeFormat::FormatTime24H
    class TimeSetSpinnerVertical : public VBox
    class ClockVertical : public VBox
    {
      public:
        TimeSetSpinnerVertical(
            Item *parent                               = nullptr,
            uint32_t x                                 = 0U,
            uint32_t y                                 = 0U,
            uint32_t w                                 = 0U,
            uint32_t h                                 = 0U,
            utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::TimeFormat::FormatTime12H);
        ClockVertical(Item *parent                               = nullptr,
                      uint32_t x                                 = 0U,
                      uint32_t y                                 = 0U,
                      uint32_t w                                 = 0U,
                      uint32_t h                                 = 0U,
                      utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::TimeFormat::FormatTime12H);

        /// Switches currently displayed time format
        auto setTimeFormat(utils::time::Locale::TimeFormat fmt) noexcept -> void;


@@ 57,25 52,18 @@ namespace gui

        auto getTimeFormat() const noexcept -> utils::time::Locale::TimeFormat;

        auto getHourMargins(const std::string &font) const noexcept -> Margins;

      private:
        std::map<std::string, Margins> spaceMarginsMap = {
            {style::window::font::verybiglight, {0, 0, 0, style::time_set_spinner_vertical::small_margin}},
            {style::window::font::largelight, {0, 0, 0, style::time_set_spinner_vertical::small_margin}},
            {style::window::font::supersizemelight, {0, 0, 0, style::time_set_spinner_vertical::big_margin}},
            {style::window::font::huge, {0, 0, 0, style::time_set_spinner_vertical::big_margin}},
            {style::window::font::colossal, {0, 0, 0, style::time_set_spinner_vertical::colossal_margin}}};

        void handleContentChanged() override;

        gui::HBox *hBoxHours             = nullptr;
        gui::HBox *hBoxHoursLeft         = nullptr;
        gui::HBox *hBoxHoursRight        = nullptr;
        gui::HBox *hBoxMinutes           = nullptr;
        gui::HBox *hBoxMinutesLeft       = nullptr;
        gui::HBox *hBoxMinutesRight      = nullptr;
        gui::TextFixedSize *hourFirst    = nullptr;
        gui::TextFixedSize *hourSecond   = nullptr;
        gui::TextFixedSize *minuteFirst  = nullptr;
        gui::TextFixedSize *minuteSecond = nullptr;
        std::string fontName         = style::window::font::supersizemelight;
        std::string fontName             = style::window::font::supersizemelight;

        utils::time::Locale::TimeFormat timeFormat = utils::time::Locale::TimeFormat::FormatTime12H;
    };

M products/BellHybrid/apps/common/include/common/widgets/LayoutVertical.hpp => products/BellHybrid/apps/common/include/common/widgets/LayoutVertical.hpp +9 -8
@@ 9,12 9,13 @@

namespace style::homescreen_vertical
{
    constexpr inline auto side_box_w   = 120U;
    constexpr inline auto center_box_w = 240U;
    constexpr inline auto center_box_h = 220U;
    constexpr inline auto bottomMargin = 35U;
    constexpr inline auto leftMargin   = 60U;
    constexpr inline auto rightMargin  = 60U;
    constexpr inline auto side_box_w        = 115U;
    constexpr inline auto center_box_w      = 250U;
    constexpr inline auto center_box_h      = 220U;
    constexpr inline auto digit_box_w       = 125U;
    constexpr inline auto leftMargin        = 60U;
    constexpr inline auto rightMargin       = 60U;
    constexpr inline auto topNegativeMargin = -35;
} // namespace style::homescreen_vertical

namespace gui


@@ 23,7 24,7 @@ namespace gui
    class TextFixedSize;
    class AlarmIcon;
    class AlarmSetSpinner;
    class TimeSetSpinnerVertical;
    class ClockVertical;
    class TimeSetFmtSpinner;
    class SnoozeTimer;
    class BellBattery;


@@ 43,7 44,7 @@ namespace gui
        BellBattery *battery{};

        // Main Screen
        TimeSetSpinnerVertical *time{};
        ClockVertical *time{};
        VBox *leftBox{};
        VBox *rightBox{};


M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVertical.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVertical.cpp +1 -1
@@ 16,7 16,7 @@
#include <time/time_constants.hpp>
#include <widgets/AlarmIcon.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/TimeSetSpinnerVertical.hpp>
#include <widgets/ClockVertical.hpp>

namespace gui
{

M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalSimple.cpp +1 -1
@@ 15,7 15,7 @@
#include <time/time_constants.hpp>
#include <widgets/AlarmIcon.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/TimeSetSpinnerVertical.hpp>
#include <widgets/ClockVertical.hpp>

namespace gui
{

M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalWithAmPm.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutVerticalWithAmPm.cpp +1 -1
@@ 14,7 14,7 @@
#include <time/time_constants.hpp>
#include <widgets/AlarmIcon.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/TimeSetSpinnerVertical.hpp>
#include <widgets/ClockVertical.hpp>

namespace gui
{

A products/BellHybrid/apps/common/src/widgets/ClockVertical.cpp => products/BellHybrid/apps/common/src/widgets/ClockVertical.cpp +225 -0
@@ 0,0 1,225 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <common/widgets/ClockVertical.hpp>
#include "widgets/LayoutVertical.hpp"

#include <date/date.h>
#include <gui/core/FontManager.hpp>
#include <gui/core/RawFont.hpp>
#include <widgets/spinners/Spinners.hpp>

static constexpr auto doubleDigit = 10;

namespace gui
{

    ClockVertical::ClockVertical(
        Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h, utils::time::Locale::TimeFormat timeFormat)
        : VBox{parent, x, y, w, h}
    {
        using namespace utils;

        setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        setEdges(RectangleEdge::None);

        hBoxHours = new gui::HBox(this, 0, 0, style::homescreen_vertical::center_box_w, 0);
        hBoxHours->setEdges(gui::RectangleEdge::None);
        hBoxHours->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        hBoxHours->setMinimumSize(style::homescreen_vertical::center_box_w, style::homescreen_vertical::center_box_h);
        hBoxHours->setMargins(gui::Margins(0, 0, 0, style::homescreen_vertical::topNegativeMargin));

        hBoxHoursLeft = new gui::HBox(hBoxHours, 0, 0, 0, 0);
        hBoxHoursLeft->setEdges(gui::RectangleEdge::None);
        hBoxHoursLeft->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        hBoxHoursLeft->setMaximumSize(style::homescreen_vertical::digit_box_w,
                                      style::homescreen_vertical::center_box_h);

        hBoxHoursRight = new gui::HBox(hBoxHours, 0, 0, 0, 0);
        hBoxHoursRight->setEdges(gui::RectangleEdge::None);
        hBoxHoursRight->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        hBoxHoursRight->setMaximumSize(style::homescreen_vertical::digit_box_w,
                                       style::homescreen_vertical::center_box_h);

        hourFirst = new gui::TextFixedSize(hBoxHoursLeft, 0, 0, 0, 0);
        updateFont(hourFirst, fontName);

        hourFirst->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        hourFirst->setEdges(RectangleEdge::None);
        hourFirst->setText("0");
        hourFirst->drawUnderline(false);

        hourSecond = new gui::TextFixedSize(hBoxHoursRight, 0, 0, 0, 0);
        updateFont(hourSecond, fontName);

        hourSecond->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        hourSecond->setEdges(RectangleEdge::None);
        hourSecond->setText("0");
        hourSecond->drawUnderline(false);

        hBoxMinutes = new gui::HBox(this, 0, 0, style::homescreen_vertical::center_box_w, 0);
        hBoxMinutes->setEdges(gui::RectangleEdge::None);
        hBoxMinutes->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        hBoxMinutes->setMargins(gui::Margins(0, 0, 0, 0));
        hBoxMinutes->setMinimumSize(style::homescreen_vertical::center_box_w, style::homescreen_vertical::center_box_h);

        hBoxMinutesLeft = new gui::HBox(hBoxMinutes, 0, 0, 0, 0);
        hBoxMinutesLeft->setEdges(gui::RectangleEdge::None);
        hBoxMinutesLeft->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        hBoxMinutesLeft->setMaximumSize(style::homescreen_vertical::digit_box_w,
                                        style::homescreen_vertical::center_box_h);

        hBoxMinutesRight = new gui::HBox(hBoxMinutes, 0, 0, 0, 0);
        hBoxMinutesRight->setEdges(gui::RectangleEdge::None);
        hBoxMinutesRight->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        hBoxMinutesRight->setMaximumSize(style::homescreen_vertical::digit_box_w,
                                         style::homescreen_vertical::center_box_h);

        minuteFirst = new gui::TextFixedSize(hBoxMinutesLeft, 0, 0, 0, 0);
        updateFont(minuteFirst, fontName);

        minuteFirst->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        minuteFirst->setEdges(RectangleEdge::None);
        minuteFirst->setText("0");
        minuteFirst->drawUnderline(false);

        minuteSecond = new gui::TextFixedSize(hBoxMinutesRight, 0, 0, 0, 0);
        updateFont(minuteSecond, fontName);

        minuteSecond->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        minuteSecond->setEdges(RectangleEdge::None);
        minuteSecond->setText("0");
        minuteSecond->drawUnderline(false);

        resizeItems();

        setTimeFormat(timeFormat);
    }

    auto ClockVertical::setTimeFormat(utils::time::Locale::TimeFormat newFormat) noexcept -> void
    {
        using namespace utils;

        const auto hourFirstStr  = hourFirst->getText();
        const auto hourSecondStr = hourSecond->getText();
        const auto hoursStr      = hourFirstStr + hourSecondStr;
        const auto hoursInt      = std::stoi(hoursStr.c_str());
        const auto hours         = std::chrono::hours(hoursInt);

        timeFormat = newFormat;

        switch (newFormat) {
        case utils::time::Locale::TimeFormat::FormatTime12H: {
            if (timeFormat != newFormat) {
                const auto time12H = date::make12(hours);
                setHour(time12H.count());
            }

        } break;
        case utils::time::Locale::TimeFormat::FormatTime24H: {
            if (newFormat != timeFormat) {
                const auto time24H = date::make24(hours, isPM());
                setHour(time24H.count());
            }
        } break;
        default:
            break;
        }

        timeFormat = newFormat;
    }

    auto ClockVertical::setMinute(int value) noexcept -> void
    {
        const auto valueStr = std::to_string(value);
        if (value < doubleDigit) {
            minuteFirst->setText("0");
            minuteSecond->setText(valueStr.substr(0, 1));
        }
        else {
            minuteFirst->setText(valueStr.substr(0, 1));
            minuteSecond->setText(valueStr.substr(1, 1));
        }
    }

    auto ClockVertical::getHour() const noexcept -> int
    {
        auto hourFirstStr  = hourFirst->getText();
        auto hourSecondStr = hourSecond->getText();
        auto hoursStr      = hourFirstStr + hourSecondStr;
        return std::stoi(hoursStr.c_str());
    }

    auto ClockVertical::getMinute() const noexcept -> int
    {
        auto minuteFirstStr  = minuteFirst->getText();
        auto minuteSecondStr = minuteSecond->getText();
        auto minutesStr      = minuteFirstStr + minuteSecondStr;
        return std::stoi(minutesStr.c_str());
    }

    auto ClockVertical::setHour(int value) noexcept -> void
    {
        auto valueStr = std::to_string(value);
        if (value < doubleDigit) {
            hourFirst->setText("0");
            hourSecond->setText(valueStr.substr(0, 1));
        }
        else {
            hourFirst->setText(valueStr.substr(0, 1));
            hourSecond->setText(valueStr.substr(1, 1));
        }
    }

    auto ClockVertical::updateFont(TextFixedSize *elem, const std::string &fontName) noexcept -> void
    {
        elem->setFont(fontName);
        elem->setMinimumHeightToFitText();
        elem->setMinimumWidthToFitText();

        elem->setText(elem->getText());
    }

    auto ClockVertical::setFont(const std::string &newFontName) noexcept -> void
    {
        fontName = newFontName;

        updateFont(hourFirst, fontName);
        updateFont(hourSecond, fontName);
        updateFont(minuteFirst, fontName);
        updateFont(minuteSecond, fontName);

        resizeItems();
    }

    auto ClockVertical::isPM() const noexcept -> bool
    {
        return timeFormat == utils::time::Locale::TimeFormat::FormatTime12H;
    }

    auto ClockVertical::getTimeFormat() const noexcept -> utils::time::Locale::TimeFormat
    {
        return timeFormat;
    }

    auto ClockVertical::setTime(std::time_t time) noexcept -> void
    {
        using namespace utils::time;
        const auto t     = std::localtime(&time);
        const auto hours = std::chrono::hours{t->tm_hour};

        switch (timeFormat) {
        case utils::time::Locale::TimeFormat::FormatTime12H: {
            const auto hours12H = date::make12(hours);
            setHour(hours12H.count());
        } break;
        case utils::time::Locale::TimeFormat::FormatTime24H: {
            setHour(hours.count());
        } break;
        default:
            break;
        }

        setMinute(t->tm_min);
    }
} // namespace gui

M products/BellHybrid/apps/common/src/widgets/LayoutVertical.cpp => products/BellHybrid/apps/common/src/widgets/LayoutVertical.cpp +3 -3
@@ 16,7 16,7 @@
#include <time/time_constants.hpp>
#include <widgets/AlarmIcon.hpp>
#include <widgets/AlarmSetSpinner.hpp>
#include <widgets/TimeSetSpinnerVertical.hpp>
#include <widgets/ClockVertical.hpp>

namespace gui
{


@@ 39,7 39,7 @@ namespace gui
        centerBox->setMinimumSize(style::homescreen_vertical::center_box_w, style::window_height);
        centerBox->setEdges(RectangleEdge::None);

        time = new TimeSetSpinnerVertical(centerBox);
        time = new ClockVertical(centerBox);
        time->setFont(style::window::font::colossal);
        time->setMinimumSize(style::homescreen_vertical::center_box_w, style::window_height);
        time->setEdges(RectangleEdge::None);


@@ 98,7 98,7 @@ namespace gui
        alarmActivatedDeactivatedScreen->text->setFont(style::window::font::verybiglight);
        alarmActivatedDeactivatedScreen->resizeItems();
        alarmActivatedDeactivatedScreen->setVisible(false);
        alarmActivatedDeactivatedScreen->image->setEdges(RectangleEdge::All);
        alarmActivatedDeactivatedScreen->image->setEdges(RectangleEdge::None);

        resizeItems();
    }

D products/BellHybrid/apps/common/src/widgets/TimeSetSpinnerVertical.cpp => products/BellHybrid/apps/common/src/widgets/TimeSetSpinnerVertical.cpp +0 -271
@@ 1,271 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <common/widgets/TimeSetSpinnerVertical.hpp>
#include "widgets/LayoutVertical.hpp"

#include <date/date.h>
#include <gui/core/FontManager.hpp>
#include <gui/core/RawFont.hpp>
#include <widgets/spinners/Spinners.hpp>

static constexpr auto doubleDigit = 10;

namespace gui
{

    TimeSetSpinnerVertical::TimeSetSpinnerVertical(
        Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h, utils::time::Locale::TimeFormat timeFormat)
        : VBox{parent, x, y, w, h}
    {
        using namespace utils;

        setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        setEdges(RectangleEdge::None);

        hBoxHours = new gui::HBox(
            this, 0, 0, style::homescreen_vertical::center_box_w, style::homescreen_vertical::center_box_h);
        hBoxHours->setEdges(gui::RectangleEdge::None);
        hBoxHours->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));

        hourFirst = new gui::TextFixedSize(hBoxHours, 0, 0, 0, 0);
        updateFont(hourFirst, fontName);

        hourFirst->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
        hourFirst->setEdges(RectangleEdge::None);
        hourFirst->setText("0");
        hourFirst->setMargins(getHourMargins(fontName));

        hourSecond = new gui::TextFixedSize(hBoxHours, 0, 0, 0, 0);
        updateFont(hourSecond, fontName);

        hourSecond->setAlignment(Alignment(Alignment::Horizontal::Right, Alignment::Vertical::Center));
        hourSecond->setEdges(RectangleEdge::None);
        hourSecond->setText("0");
        hourSecond->setMargins(getHourMargins(fontName));

        hBoxHours->addWidget(hourFirst);
        hBoxHours->addWidget(hourSecond);

        hBoxMinutes = new gui::HBox(
            this, 0, 0, style::homescreen_vertical::center_box_w, style::homescreen_vertical::center_box_h);
        hBoxMinutes->setEdges(gui::RectangleEdge::None);
        hBoxMinutes->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        hBoxMinutes->setMargins(gui::Margins(0, 0, 0, style::homescreen_vertical::bottomMargin));

        minuteFirst = new gui::TextFixedSize(hBoxMinutes, 0, 0, 0, 0);
        updateFont(minuteFirst, fontName);

        minuteFirst->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Top));
        minuteFirst->setEdges(RectangleEdge::None);
        minuteFirst->setText("0");
        minuteFirst->drawUnderline(false);

        minuteSecond = new gui::TextFixedSize(hBoxMinutes, 0, 0, 0, 0);
        updateFont(minuteSecond, fontName);

        minuteSecond->setAlignment(Alignment(Alignment::Horizontal::Right, Alignment::Vertical::Top));
        minuteSecond->setEdges(RectangleEdge::None);
        minuteSecond->setText("0");
        minuteSecond->drawUnderline(false);

        hBoxMinutes->addWidget(minuteFirst);
        hBoxMinutes->addWidget(minuteSecond);

        resizeItems();

        setTimeFormat(timeFormat);
    }

    auto TimeSetSpinnerVertical::setTimeFormat(utils::time::Locale::TimeFormat newFormat) noexcept -> void
    {
        using namespace utils;

        const auto hourFirstStr  = hourFirst->getText();
        const auto hourSecondStr = hourSecond->getText();
        const auto hoursStr      = hourFirstStr + hourSecondStr;
        const auto hoursInt      = std::stoi(hoursStr.c_str());
        const auto hours         = std::chrono::hours(hoursInt);

        switch (newFormat) {
        case utils::time::Locale::TimeFormat::FormatTime12H: {
            if (timeFormat != newFormat) {
                const auto time12H    = date::make12(hours);
                const auto stringHour = std::to_string(time12H.count());
                if (hoursInt < doubleDigit) {
                    hourFirst->setText("0");
                    hourSecond->setText(stringHour.substr(0, 1));
                }
                else {
                    hourFirst->setText(stringHour.substr(0, 1));
                    hourSecond->setText(stringHour.substr(1, 1));
                }
            }

        } break;
        case utils::time::Locale::TimeFormat::FormatTime24H: {
            if (newFormat != timeFormat) {
                const auto time24H    = date::make24(hours, isPM());
                const auto stringHour = std::to_string(time24H.count());
                if (hoursInt < doubleDigit) {
                    hourFirst->setText("0");
                    hourSecond->setText(stringHour.substr(0, 1));
                }
                else {
                    hourFirst->setText(stringHour.substr(0, 1));
                    hourSecond->setText(stringHour.substr(1, 1));
                }
            }
        } break;
        default:
            break;
        }

        timeFormat = newFormat;
    }

    auto TimeSetSpinnerVertical::setMinute(int value) noexcept -> void
    {
        const auto valueStr = std::to_string(value);
        if (value < doubleDigit) {
            minuteFirst->setText("0");
            minuteSecond->setText(valueStr.substr(0, 1));
        }
        else {
            minuteFirst->setText(valueStr.substr(0, 1));
            minuteSecond->setText(valueStr.substr(1, 1));
        }
    }

    auto TimeSetSpinnerVertical::getHour() const noexcept -> int
    {
        auto hourFirstStr  = hourFirst->getText();
        auto hourSecondStr = hourSecond->getText();
        auto hoursStr      = hourFirstStr + hourSecondStr;
        return std::stoi(hoursStr.c_str());
    }

    auto TimeSetSpinnerVertical::getMinute() const noexcept -> int
    {
        auto minuteFirstStr  = minuteFirst->getText();
        auto minuteSecondStr = minuteSecond->getText();
        auto minutesStr      = minuteFirstStr + minuteSecondStr;
        return std::stoi(minutesStr.c_str());
    }

    auto TimeSetSpinnerVertical::setHour(int value) noexcept -> void
    {
        auto valueStr = std::to_string(value);
        if (value < doubleDigit) {
            hourFirst->setText("0");
            hourSecond->setText(valueStr.substr(0, 1));
        }
        else {
            hourFirst->setText(valueStr.substr(0, 1));
            hourSecond->setText(valueStr.substr(1, 1));
        }
    }

    auto TimeSetSpinnerVertical::updateFont(TextFixedSize *elem, const std::string &fontName) noexcept -> void
    {
        elem->setFont(fontName);
        elem->setMinimumHeightToFitText();
        elem->setMinimumWidthToFitText();

        elem->setText(elem->getText());
    }

    auto TimeSetSpinnerVertical::setFont(const std::string &newFontName) noexcept -> void
    {
        fontName = newFontName;

        updateFont(hourFirst, fontName);
        updateFont(hourSecond, fontName);
        updateFont(minuteFirst, fontName);
        updateFont(minuteSecond, fontName);
        auto hourMargins = getHourMargins(fontName);
        hourFirst->setMargins(getHourMargins(fontName));
        hourSecond->setMargins(getHourMargins(fontName));

        auto hourArea   = hourFirst->widgetMinimumArea.w + hourSecond->widgetMinimumArea.w;
        auto minuteArea = minuteFirst->widgetMinimumArea.w + minuteSecond->widgetMinimumArea.w;

        auto width = hourArea > minuteArea ? hourArea : minuteArea;

        auto verticalMargin = hourMargins.top + hourMargins.bottom;
        setMinimumSize(width, hourArea + minuteArea + verticalMargin);
        resizeItems();
    }

    auto TimeSetSpinnerVertical::isPM() const noexcept -> bool
    {
        return timeFormat == utils::time::Locale::TimeFormat::FormatTime12H;
    }

    auto TimeSetSpinnerVertical::getTimeFormat() const noexcept -> utils::time::Locale::TimeFormat
    {
        return timeFormat;
    }

    auto TimeSetSpinnerVertical::setTime(std::time_t time) noexcept -> void
    {
        using namespace utils::time;
        const auto t = std::localtime(&time);
        const auto hours = std::chrono::hours{t->tm_hour};

        if (timeFormat == Locale::TimeFormat::FormatTime24H) {
            const auto time24H = date::make24(hours, isPM());
            auto stringHour    = std::to_string(time24H.count());

            if (t->tm_hour < doubleDigit) {
                hourFirst->setText("0");
                hourSecond->setText(stringHour.substr(0, 1));
            }
            else {
                hourFirst->setText(stringHour.substr(0, 1));
                hourSecond->setText(stringHour.substr(1, 1));
            }
        }
        else {
            const auto time12H = date::make12(hours);
            auto stringHour    = std::to_string(time12H.count());
            auto hourInt       = std::stoi(stringHour.c_str());

            if (hourInt < doubleDigit) {
                hourFirst->setText("0");
                hourSecond->setText(stringHour.substr(0, 1));
            }
            else {
                hourFirst->setText(stringHour.substr(0, 1));
                hourSecond->setText(stringHour.substr(1, 1));
            }
        }

        setMinute(t->tm_min);
        handleContentChanged();
    }

    void TimeSetSpinnerVertical::handleContentChanged()
    {
        hourFirst->setMinimumWidthToFitText();
        hourSecond->setMinimumWidthToFitText();
        minuteFirst->setMinimumWidthToFitText();
        minuteSecond->setMinimumWidthToFitText();

        auto hourArea   = hourFirst->widgetMinimumArea.w + hourSecond->widgetMinimumArea.w;
        auto minuteArea = minuteFirst->widgetMinimumArea.w + minuteSecond->widgetMinimumArea.w;

        auto width = hourArea > minuteArea ? hourArea : minuteArea;

        setMinimumSize(width, hourArea + minuteArea + 10);
        setMaximumWidth(widgetMinimumArea.w);

        VBox::informContentChanged();
    }

    auto TimeSetSpinnerVertical::getHourMargins(const std::string &font) const noexcept -> Margins
    {
        return spaceMarginsMap.find(font)->second;
    }

} // namespace gui