mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-01-01 02:19:00 -05:00
* Fix of the issue that after changing font size of the clock presented in Relaxation, Meditation and Power Nap apps, AM/PM label was not shown in 12h mode. * Added logs informing about missing margins map entry so that such issue is easier to debug if it should happen in the future.
317 lines
10 KiB
C++
317 lines
10 KiB
C++
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include "TimeSetFmtSpinner.hpp"
|
|
|
|
#include <date/date.h>
|
|
#include <gui/core/FontManager.hpp>
|
|
#include <gui/core/RawFont.hpp>
|
|
#include <widgets/spinners/Spinners.hpp>
|
|
|
|
namespace gui
|
|
{
|
|
TimeSetFmtSpinner::TimeSetFmtSpinner(Item *parent) : HBox{parent}
|
|
{
|
|
using namespace utils;
|
|
|
|
setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
|
|
setEdges(RectangleEdge::None);
|
|
|
|
timeSetSpinner = new TimeSetSpinner(nullptr);
|
|
timeSetSpinner->setFont(focusFontName, noFocusFontName);
|
|
timeSetSpinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
|
|
|
|
auto textRange = {time::Locale::getAM(), time::Locale::getPM()};
|
|
fmt = new StringSpinner(textRange, Boundaries::Continuous);
|
|
updateFmtFont(noFocusFontName);
|
|
fmt->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
|
|
fmt->setMargins(getFmtMargins(noFocusFontName));
|
|
fmt->setVisible(false);
|
|
fmt->setPenFocusWidth(style::time_set_spinner::focus::size);
|
|
fmt->setEdges(RectangleEdge::Bottom);
|
|
|
|
addWidget(timeSetSpinner);
|
|
addWidget(fmt);
|
|
|
|
setTimeFormat(timeFormat, false);
|
|
|
|
resizeItems();
|
|
|
|
focusChangedCallback = [&](Item &) {
|
|
if (focus) {
|
|
setTimeFormat(this->timeFormat);
|
|
if (editMode == EditMode::Edit) {
|
|
setFocusItem(timeSetSpinner);
|
|
}
|
|
}
|
|
else {
|
|
setFocusItem(nullptr);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
fmt->focusChangedCallback = [&](Item &) {
|
|
if (fmt->focus) {
|
|
updateFmtFont(focusFontName);
|
|
}
|
|
else {
|
|
updateFmtFont(noFocusFontName);
|
|
}
|
|
return true;
|
|
};
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setTimeFormat(utils::time::Locale::TimeFormat newFormat) noexcept -> void
|
|
{
|
|
setTimeFormat(newFormat, true);
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setTimeFormat(utils::time::Locale::TimeFormat newFormat, bool informContentChanged) noexcept
|
|
-> void
|
|
{
|
|
using namespace utils;
|
|
|
|
switch (newFormat) {
|
|
case utils::time::Locale::TimeFormat::FormatTime12H: {
|
|
fmt->setVisible(true);
|
|
auto hours = std::chrono::hours(timeSetSpinner->getHour());
|
|
timeSetSpinner->setHourRange(time::Locale::min_hour_12H_mode, time::Locale::max_hour_12H_mode);
|
|
|
|
if (timeFormat != newFormat) {
|
|
timeSetSpinner->setHour(date::make12(hours).count());
|
|
set12HPeriod(date::is_pm(hours) ? Period::PM : Period::AM);
|
|
}
|
|
|
|
} break;
|
|
|
|
case utils::time::Locale::TimeFormat::FormatTime24H: {
|
|
fmt->setVisible(false);
|
|
auto hours = std::chrono::hours(timeSetSpinner->getHour());
|
|
timeSetSpinner->setHourRange(time::Locale::min_hour_24H_mode, time::Locale::max_hour_24H_mode);
|
|
|
|
if (newFormat != timeFormat) {
|
|
timeSetSpinner->setHour(date::make24(hours, isPM()).count());
|
|
|
|
if (focusItem == fmt) {
|
|
setFocusItem(timeSetSpinner);
|
|
}
|
|
}
|
|
} break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
timeFormat = newFormat;
|
|
|
|
if (informContentChanged) {
|
|
fmt->handleContentChanged();
|
|
}
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setMinute(int value) noexcept -> void
|
|
{
|
|
timeSetSpinner->setMinute(value);
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setEditMode(EditMode newEditMode) noexcept -> void
|
|
{
|
|
editMode = newEditMode;
|
|
if (editMode == EditMode::Edit) {
|
|
setFocusItem(timeSetSpinner);
|
|
timeSetSpinner->setEditMode(editMode);
|
|
}
|
|
else {
|
|
setFocusItem(nullptr);
|
|
}
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getHour() const noexcept -> int
|
|
{
|
|
return timeSetSpinner->getHour();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getMinute() const noexcept -> int
|
|
{
|
|
return timeSetSpinner->getMinute();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getFmtMargins(const std::string &fmtFont) const noexcept -> Margins
|
|
{
|
|
const auto fmtMargin = fmtMarginsMap.find(fmtFont);
|
|
if (fmtMargin == fmtMarginsMap.end()) {
|
|
LOG_ERROR("Missing margins map entry for font '%s', update margins map! Fallback value (zero) will be set.",
|
|
fmtFont.c_str());
|
|
return Margins();
|
|
}
|
|
return fmtMargin->second;
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setHour(int value) noexcept -> void
|
|
{
|
|
timeSetSpinner->setHour(value);
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setFont(std::string newFontName) noexcept -> void
|
|
{
|
|
setFont(newFontName, newFontName);
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setFont(std::string newFocusFontName, std::string newNoFocusFontName) noexcept -> void
|
|
{
|
|
focusFontName = std::move(newFocusFontName);
|
|
noFocusFontName = std::move(newNoFocusFontName);
|
|
|
|
timeSetSpinner->setFont(focusFontName, noFocusFontName);
|
|
updateFmtFont(noFocusFontName);
|
|
|
|
setMinimumSize(timeSetSpinner->widgetMinimumArea.w + fmt->widgetMinimumArea.w +
|
|
fmt->margins.getSumInAxis(Axis::X),
|
|
timeSetSpinner->widgetMinimumArea.h);
|
|
resizeItems();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::updateFmtFont(const std::string &fontName) noexcept -> void
|
|
{
|
|
fmt->setFont(fontName);
|
|
fmt->setMinimumWidthToFitText();
|
|
fmt->setMinimumHeightToFitText();
|
|
fmt->setMargins(getFmtMargins(fontName));
|
|
fmt->setText(fmt->getText());
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::onInput(const InputEvent &inputEvent) -> bool
|
|
{
|
|
// Ignore input event when not in edit mode
|
|
if (editMode != EditMode::Edit) {
|
|
return false;
|
|
}
|
|
|
|
if (auto ret = this->focusItem->onInput(inputEvent)) {
|
|
return ret;
|
|
}
|
|
|
|
if (inputEvent.isShortRelease()) {
|
|
switch (inputEvent.getKeyCode()) {
|
|
case KeyCode::KEY_ENTER:
|
|
return handleEnterKey();
|
|
case KeyCode::KEY_RF:
|
|
return handleRightFunctionKey();
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::handleEnterKey() -> bool
|
|
{
|
|
using namespace utils::time;
|
|
if ((focusItem == timeSetSpinner) && (timeFormat == Locale::TimeFormat::FormatTime12H)) {
|
|
setFocusItem(fmt);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::handleRightFunctionKey() -> bool
|
|
{
|
|
if (focusItem == fmt) {
|
|
setFocusItem(timeSetSpinner);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::isPM() const noexcept -> bool
|
|
{
|
|
return fmt->value() == utils::time::Locale::getPM().c_str();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getTimeFormat() const noexcept -> utils::time::Locale::TimeFormat
|
|
{
|
|
return timeFormat;
|
|
}
|
|
|
|
void TimeSetFmtSpinner::setVisible(bool value)
|
|
{
|
|
HBox::setVisible(value);
|
|
// This is a workaround for fmt visibility not changed properly
|
|
// It's probably caused by a bug in BoxLayout
|
|
fmt->setVisible(value);
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setTime(std::time_t time) noexcept -> void
|
|
{
|
|
using namespace utils::time;
|
|
if (timeFormat == Locale::TimeFormat::FormatTime24H) {
|
|
timeSetSpinner->setTime(time);
|
|
}
|
|
else {
|
|
const auto t = std::localtime(&time);
|
|
const auto hours = std::chrono::hours{t->tm_hour};
|
|
const auto time12H = date::make12(hours);
|
|
const auto isPM = date::is_pm(hours);
|
|
fmt->set_value(isPM ? utils::time::Locale::getPM() : utils::time::Locale::getAM());
|
|
timeSetSpinner->setTime(time12H.count(), t->tm_min);
|
|
}
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::setTimeFormatSpinnerVisibility(bool visibility) noexcept -> void
|
|
{
|
|
fmt->setVisible(visibility);
|
|
resizeItems();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getTime() const noexcept -> std::time_t
|
|
{
|
|
using namespace utils::time;
|
|
const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
const auto newTime = std::localtime(&now);
|
|
if (timeFormat == Locale::TimeFormat::FormatTime24H) {
|
|
newTime->tm_hour = timeSetSpinner->getHour();
|
|
}
|
|
else {
|
|
newTime->tm_hour = date::make24(std::chrono::hours{timeSetSpinner->getHour()}, isPM()).count();
|
|
}
|
|
newTime->tm_min = timeSetSpinner->getMinute();
|
|
|
|
return std::mktime(newTime);
|
|
}
|
|
|
|
void TimeSetFmtSpinner::handleContentChanged()
|
|
{
|
|
auto widthToSet = timeSetSpinner->widgetMinimumArea.w;
|
|
|
|
if (timeFormat == utils::time::Locale::TimeFormat::FormatTime12H && fmt->visible) {
|
|
fmt->setMinimumWidthToFitText();
|
|
fmt->setMargins(getFmtMargins(noFocusFontName));
|
|
widthToSet =
|
|
timeSetSpinner->widgetMinimumArea.w + fmt->widgetMinimumArea.w + fmt->margins.getSumInAxis(Axis::X);
|
|
}
|
|
|
|
setMinimumWidth(widthToSet);
|
|
setMaximumWidth(widthToSet);
|
|
|
|
HBox::handleContentChanged();
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::set12HPeriod(const Period period) -> void
|
|
{
|
|
period == Period::AM ? fmt->set_value(utils::time::Locale::getAM())
|
|
: fmt->set_value(utils::time::Locale::getPM());
|
|
}
|
|
|
|
auto TimeSetFmtSpinner::getHour24Format() const noexcept -> int
|
|
{
|
|
using namespace utils::time;
|
|
if (timeFormat == Locale::TimeFormat::FormatTime24H) {
|
|
return timeSetSpinner->getHour();
|
|
}
|
|
auto hours = std::chrono::hours(timeSetSpinner->getHour());
|
|
return date::make24(hours, isPM()).count();
|
|
}
|
|
} // namespace gui
|