// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "Style.hpp" #include "TimerProperty.hpp" #include #include #include using namespace gui; TimerProperty::TimerProperty(Item *parent, const uint32_t x, const uint32_t y, const uint32_t w, const uint32_t h) : Rect(parent, x, y, w, h) { build(); } void TimerProperty::build() { namespace timerStyle = style::meditation::timer; const Point boxCenter(getX() + (getWidth() / 2), getY() + (getHeight() / 2)); Circle::ShapeParams params; params.setCenterPoint(boxCenter) .setRadius(timerStyle::Radius) .setBorderColor(timerStyle::BorderColor) .setFocusBorderColor(timerStyle::BorderColor) .setPenWidth(timerStyle::PenWidth) .setFocusPenWidth(timerStyle::FocusPenWidth); circle = new Circle(this, params); centerBody = new VBox(this, 0, 0, 2 * timerStyle::Radius, 2 * timerStyle::Radius); centerBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top)); centerBody->setMinimumSize(2 * timerStyle::Radius, 2 * timerStyle::Radius); centerBody->setEdges(RectangleEdge::None); centerBody->activeItem = false; timeLabel = new Label(centerBody); timeLabel->setMargins(gui::Margins(0, timerStyle::setterValueLabel::TopMargin, 0, 0)); timeLabel->setEdges(RectangleEdge::None); timeLabel->setMinimumSize(timerStyle::setterValueLabel::Width, timerStyle::setterValueLabel::Height); timeLabel->setFont(style::window::font::supersizemelight); timeLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); timeLabel->setPenWidth(timerStyle::PenWidth); timeLabel->setText(std::to_string(static_cast(state.getTime().count()))); divRect = new Rect(centerBody, 0, 0, timerStyle::setterValueLabel::BottomLineWidth, 1); divRect->setPenWidth(timerStyle::setterValueLabel::BottomLinePen); timeUnitLabel = new Label(centerBody); timeUnitLabel->setMinimumSize(timerStyle::setterUnitLabel::Width, timerStyle::setterUnitLabel::Height); timeUnitLabel->setMargins(gui::Margins(0, timerStyle::setterUnitLabel::TopMargin, 0, 0)); timeUnitLabel->setFont(style::window::font::verysmall); timeUnitLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); timeUnitLabel->setEdges(RectangleEdge::None); timeUnitLabel->setText(utils::translate("app_meditation_minutes")); centerBody->resizeItems(); } bool TimerProperty::onFocus(bool isFocused) { circle->setFocus(isFocused); if (isFocused) { divRect->setEdges(RectangleEdge::Top); } else { divRect->setEdges(RectangleEdge::None); } state.onFocus(); return true; } bool TimerProperty::onInput(const InputEvent &inputEvent) { bool handled = false; if (inputEvent.isShortRelease()) { if (inputEvent.isDigit()) { state.putNumericValue(inputEvent.numericValue()); handled = true; } else if (inputEvent.is(KeyCode::KEY_LEFT)) { state.decrement(); handled = true; } else if (inputEvent.is(KeyCode::KEY_RIGHT)) { state.increment(); handled = true; } else { state.onFocus(); } setMeditationTime(); } return handled; } void TimerProperty::setMeditationTime() { const auto meditationTime = static_cast(state.getTime().count()); timeLabel->setText(utils::to_string(meditationTime)); if (meditationTime == 1) { timeUnitLabel->setText(utils::translate("app_meditation_minute")); } else { timeUnitLabel->setText(utils::translate("app_meditation_minutes")); } } std::chrono::minutes TimerProperty::getTime() noexcept { state.checkBounds(); return state.getTime(); } void TimerProperty::State::checkBounds() noexcept { timeInMinutes = std::clamp(timeInMinutes, minimalValue, maximalValue); resetValueOnNumeric = true; } void TimerProperty::State::putNumericValue(int digit) noexcept { if (resetValueOnNumeric) { timeInMinutes = 0; resetValueOnNumeric = false; } timeInMinutes = 10 * timeInMinutes + digit; if (timeInMinutes >= 10 * (counterMaxDigits - 1)) { resetValueOnNumeric = true; } } void TimerProperty::State::increment() noexcept { auto it = std::upper_bound(std::begin(timeArr), std::end(timeArr), timeInMinutes); if (it == std::end(timeArr)) { it--; } timeInMinutes = *it; resetValueOnNumeric = true; } void TimerProperty::State::decrement() noexcept { auto it = std::upper_bound(std::rbegin(timeArr), std::rend(timeArr), timeInMinutes, [](int a, int b) { return a > b; }); if (it == std::rend(timeArr)) { it--; } timeInMinutes = *it; resetValueOnNumeric = true; }