~aleteoryx/muditaos

4ec11baf9b761dbb0c859bb7f3918a62b8dde9c7 — Mateusz Piesta 4 years ago 1f0d51d
[BH-675] Add TextSpinner

Added TextSpinner widget
M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +2 -0
@@ 29,6 29,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/SideListItem.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListView.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Spinner.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TextSpinner.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SIM.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/BatteryBase.cpp"


@@ 84,6 85,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/SideListItem.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListView.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Spinner.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/TextSpinner.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Text.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/header/Header.hpp"

A module-gui/gui/widgets/TextSpinner.cpp => module-gui/gui/widgets/TextSpinner.cpp +106 -0
@@ 0,0 1,106 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TextSpinner.hpp"

namespace gui
{
    TextSpinner::TextSpinner(const TextSpinner::TextRange &range, Boundaries boundaries)
        : textRange{range}, boundaries(boundaries)
    {
        setEditMode(EditMode::Browse);
        update();
    }
    void TextSpinner::setTextRange(const TextSpinner::TextRange &range)
    {
        textRange = range;
        update();
    }
    void TextSpinner::setCurrentPosition(Position pos)
    {
        if ((pos >= getRangeDownLimit()) && (pos <= getRangeUpLimit())) {
            currentPosition = pos;
        }
        update();
    }

    std::string TextSpinner::getCurrentText() const noexcept
    {
        return textRange[currentPosition];
    }

    void TextSpinner::stepUp()
    {
        if (currentPosition >= getRangeUpLimit()) {
            if (boundaries == Boundaries::Continuous) {
                currentPosition = getRangeDownLimit();
            }
            else {
                currentPosition = getRangeUpLimit();
            }
        }
        else {
            currentPosition++;
        }
        update();
    }
    void TextSpinner::stepDown()
    {
        if (currentPosition <= getRangeDownLimit()) {
            if (boundaries == Boundaries::Continuous) {
                currentPosition = getRangeUpLimit();
            }
            else {
                currentPosition = getRangeDownLimit();
            }
        }
        else {
            currentPosition--;
        }
        update();
    }
    void TextSpinner::update()
    {
        setText(textRange[currentPosition]);
    }
    bool TextSpinner::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease()) {
            switch (inputEvent.getKeyCode()) {
            case KeyCode::KEY_UP:
                stepUp();
                return true;
            case KeyCode::KEY_DOWN:
                stepDown();
                return true;
            default:
                break;
            }
        }
        return false;
    }
    bool TextSpinner::onFocus(bool state)
    {
        if (focus) {
            setEdges(RectangleEdge::Top | RectangleEdge::Bottom);
        }
        else {
            setEdges(RectangleEdge::None);
        }
        showCursor(state);
        return true;
    }
    TextSpinner::Position TextSpinner::getRangeUpLimit() const
    {
        return static_cast<Position>(textRange.size() - 1);
    }
    TextSpinner::Position TextSpinner::getRangeDownLimit() const
    {
        return 0;
    }
    TextSpinner::Range TextSpinner::getValidRange() const noexcept
    {
        return Range{getRangeDownLimit(), getRangeUpLimit()};
    }

} // namespace gui

A module-gui/gui/widgets/TextSpinner.hpp => module-gui/gui/widgets/TextSpinner.hpp +47 -0
@@ 0,0 1,47 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Text.hpp"

#include <string>
#include <vector>

namespace gui
{
    class TextSpinner : public Text
    {
      public:
        using TextRange = std::vector<std::string>;
        using Position  = std::uint32_t;
        using Range     = std::pair<Position, Position>;

        TextSpinner() = delete;
        TextSpinner(const TextRange &range, Boundaries boundaries);

        /// Sets range of strings to spin over
        void setTextRange(const TextRange &range);
        /// Sets current position. Must be within valid @ref Range that can be checked by @ref getValidRange
        void setCurrentPosition(Position pos);

        [[nodiscard]] std::string getCurrentText() const noexcept;
        [[nodiscard]] Range getValidRange() const noexcept;

        void stepUp();
        void stepDown();

        // virtual methods from Item
        bool onInput(const InputEvent &inputEvent) override;
        bool onFocus(bool state) override;

      private:
        TextRange textRange;
        Position currentPosition = 0;
        Boundaries boundaries    = Boundaries::Continuous;

        void update();
        Position getRangeUpLimit() const;
        Position getRangeDownLimit() const;
    };
} // namespace gui