// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "TimerSetter.hpp" #include #include #include using namespace gui; TimerSetter::TimerSetter(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 TimerSetter::build() { const Point boxCenter(getX() + (getWidth() / 2), getY() + (getHeight() / 2)); namespace timerStyle = style::meditation::timer; Circle::ShapeParams params; params.setCenterPoint(boxCenter) .setRadius(timerStyle::Radius) .setBorderColor(timerStyle::BorderColor) .setFocusBorderColor(timerStyle::BorderColorOnFocused) .setPenWidth(timerStyle::PenWidth) .setFocusPenWidth(timerStyle::PenWidth); circle = new Circle(this, params); namespace timerStyle = style::meditation::timer; timeLabel = new Label(this, timerStyle::setterValueLabel::X, timerStyle::setterValueLabel::Y, timerStyle::setterValueLabel::Width, timerStyle::setterValueLabel::Height); timeLabel->setEdges(RectangleEdge::None); 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()))); timeUnitLabel = new Label(this, timerStyle::setterUnitLabel::X, timerStyle::setterUnitLabel::Y, timerStyle::setterUnitLabel::Width, timerStyle::setterUnitLabel::Height); timeUnitLabel->setFont(style::window::font::verysmall); timeUnitLabel->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); timeUnitLabel->setEdges(RectangleEdge::None); timeUnitLabel->setText(utils::localize.get("app_meditation_minutes")); } bool TimerSetter::onFocus(bool isFocused) { circle->setFocus(isFocused); if (isFocused) { timeLabel->setEdges(RectangleEdge::Bottom); } else { timeLabel->setEdges(RectangleEdge::None); } state.onFocus(); return true; } bool TimerSetter::onInput(const InputEvent &inputEvent) { bool handled = false; if (inputEvent.isShortPress()) { if (0 <= gui::toNumeric(inputEvent.keyCode) && gui::toNumeric(inputEvent.keyCode) <= 9) { state.putNumericValue(gui::toNumeric(inputEvent.keyCode)); 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 TimerSetter::setMeditationTime() { const auto meditationTime = static_cast(state.getTime().count()); timeLabel->setText(utils::to_string(meditationTime)); if (meditationTime == 1) { timeUnitLabel->setText(utils::localize.get("app_meditation_minute")); } else { timeUnitLabel->setText(utils::localize.get("app_meditation_minutes")); } } std::chrono::seconds TimerSetter::getTime() noexcept { state.checkBounds(); return state.getTime(); } void TimerSetter::State::checkBounds() noexcept { timeInMinutes = std::clamp(timeInMinutes, minimalValue, maximalValue); resetValueOnNumeric = true; } void TimerSetter::State::putNumericValue(int digit) noexcept { if (resetValueOnNumeric) { timeInMinutes = 0; resetValueOnNumeric = false; } timeInMinutes = 10 * timeInMinutes + digit; if (timeInMinutes >= 10 * (counterMaxDigits - 1)) { resetValueOnNumeric = true; } } void TimerSetter::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 TimerSetter::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; }