~aleteoryx/muditaos

6d344fe6cb6df6fc0ce4d83d2a6c88f078b20677 — Paweł Joński 4 years ago ebc9e56
[BH-655] Add SideListView

Add view commonly used in Bell - SideListView.
M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +7 -0
@@ 12,6 12,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/Item.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Label.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItem.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItemWithDescription.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListView.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Margins.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Navigation.cpp"


@@ 24,6 25,8 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/header/IceAction.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/header/AddElementAction.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/header/SearchAction.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListItem.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListView.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Spinner.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/status-bar/SIM.cpp"


@@ 66,6 69,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/Item.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Label.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItem.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItemWithDescription.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItemProvider.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListView.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Margins.hpp"


@@ 75,6 79,9 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/Window.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayout.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Layout.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListItem.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListItemProvider.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/SideListView.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Spinner.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/StatusBar.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Text.hpp"

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

#include "ListItemWithDescription.hpp"

namespace gui
{
    auto ListItemWithDescription::getDescription() const noexcept -> std::string
    {
        return description;
    }

    auto ListItemWithDescription::setDescription(std::string description) -> void
    {
        this->description = std::move(description);
    }
} // namespace gui

A module-gui/gui/widgets/ListItemWithDescription.hpp => module-gui/gui/widgets/ListItemWithDescription.hpp +20 -0
@@ 0,0 1,20 @@
// 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 "ListItem.hpp"

namespace gui
{
    class ListItemWithDescription : public ListItem
    {
      private:
        std::string description;

      public:
        ListItemWithDescription(std::string desc = "") : ListItem(), description(desc){};
        auto getDescription() const noexcept -> std::string;
        auto setDescription(std::string description) -> void;
    };
} /* namespace gui */

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

#include "Label.hpp"
#include "ListItemWithDescription.hpp"
#include "SideListItem.hpp"
#include "Style.hpp"

namespace gui
{
    SideListItem::SideListItem(std::string description) : ListItemWithDescription(description)
    {
        body = new HBox(this, 0U, 0U, style::sidelistview::list_item::w, style::sidelistview::list_item::h);
        body->setEdges(RectangleEdge::None);

        auto topMessage =
            new Label(body, 0U, 0U, style::sidelistview::top_message::w, style::sidelistview::top_message::h);
        topMessage->setFont(style::sidelistview::top_message::font);
        topMessage->setEdges(gui::RectangleEdge::None);
        topMessage->activeItem = false;
        topMessage->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        topMessage->setText(description);
    }
} /* namespace gui */

A module-gui/gui/widgets/SideListItem.hpp => module-gui/gui/widgets/SideListItem.hpp +18 -0
@@ 0,0 1,18 @@
// 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 "BoxLayout.hpp"
#include "ListItemWithDescription.hpp"

namespace gui
{
    class SideListItem : public ListItemWithDescription
    {
      public:
        HBox *body = nullptr;

        SideListItem(std::string description);
    };
} /* namespace gui */

A module-gui/gui/widgets/SideListItemProvider.hpp => module-gui/gui/widgets/SideListItemProvider.hpp +25 -0
@@ 0,0 1,25 @@
// 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 "ListItem.hpp"
#include "ListItemProvider.hpp"

namespace gui
{
    class SideListView;

    class SideListItemProvider
    {

      public:
        SideListView *list = nullptr;

        virtual ~SideListItemProvider() = default;

        virtual unsigned int requestRecordsCount() = 0;

        virtual ListItem *getItem(Order order) = 0;
    };
} // namespace gui

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

#include "Image.hpp"
#include "SideListView.hpp"
#include "Style.hpp"

namespace gui
{
    SideListView::SideListView(Item *parent,
                               unsigned int x,
                               unsigned int y,
                               unsigned int w,
                               unsigned int h,
                               std::shared_ptr<SideListItemProvider> prov)
        : Rect{parent, x, y, w, h}
    {

        setEdges(RectangleEdge::None);

        auto body = new VBox{this, x, y, w, h};
        body->setEdges(RectangleEdge::None);

        progressbar = new HBarGraph(body, 0U, 0U, 0U);
        progressbar->setMargins(Margins(style::sidelistview::progress_bar::margin_left,
                                        style::sidelistview::progress_bar::margin_top,
                                        style::sidelistview::progress_bar::margin_right,
                                        style::sidelistview::progress_bar::margin_bottom));
        progressbar->activeItem = false;
        progressbar->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        listItemBox = new gui::HBox(body, 0U, 0U, style::sidelistview::list_item::w, style::sidelistview::list_item::h);
        listItemBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        listItemBox->setEdges(gui::RectangleEdge::None);

        auto arrowsHBox = new HBox{this,
                                   style::sidelistview::arrows_hbox::x,
                                   style::sidelistview::arrows_hbox::y,
                                   style::sidelistview::arrows_hbox::w,
                                   style::sidelistview::arrows_hbox::h};
        arrowsHBox->setEdges(gui::RectangleEdge::None);
        auto arrowLeft = new gui::Image(style::sidelistview::arrow_left_image);
        arrowLeft->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
        arrowLeft->activeItem = false;
        arrowLeft->setEdges(RectangleEdge::None);
        arrowsHBox->addWidget(arrowLeft);

        auto arrowRight = new gui::Image(style::sidelistview::arrow_right_image);
        arrowRight->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
        arrowRight->activeItem = false;
        arrowRight->setEdges(RectangleEdge::None);

        auto rectFiller = new gui::Rect(arrowsHBox,
                                        0U,
                                        0U,
                                        arrowsHBox->getWidth() - arrowLeft->getWidth() - arrowRight->getWidth(),
                                        arrowsHBox->getHeight());

        rectFiller->setMaximumSize(arrowsHBox->getWidth(), arrowsHBox->getHeight());
        rectFiller->setEdges(RectangleEdge::None);

        arrowsHBox->addWidget(arrowRight);

        if (prov != nullptr) {
            provider       = std::move(prov);
            provider->list = this;
        }

        type = gui::ItemType::LIST;

        progressbar->setMaximum(provider->requestRecordsCount());
        progressbar->createGraph();
        progressbar->setValue(progressbarStartValue);

        if (auto firstItem = provider->getItem(Order::Next)) {
            listItemBox->addWidget(firstItem);
            listItemBox->setFocusItem(firstItem);
        }
    }

    bool SideListView::onInput(const gui::InputEvent &inputEvent)
    {
        if (auto ret = listItemBox->onInput(inputEvent)) {
            return ret;
        }

        if (inputEvent.isShortRelease(KeyCode::KEY_ENTER)) {
            if (slide(Order::Next)) {
                progressbar->setValue(progressbar->getValue() + 1);
                return true;
            }
        }
        else if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
            if (slide(Order::Previous)) {
                progressbar->setValue(progressbar->getValue() - 1);
                return true;
            }
        }

        return false;
    }

    auto SideListView::slide(gui::Order order) -> bool
    {
        auto newItem = provider->getItem(order);

        clear();
        if (newItem != nullptr) {
            listItemBox->addWidget(newItem);
            listItemBox->setFocusItem(newItem);
            return true;
        }
        return false;
    }

    SideListView::~SideListView()
    {
        clear();
    }

    void SideListView::clear()
    {
        listItemBox->setFocusItem(nullptr);

        while (auto el = listItemBox->children.back()) {
            if (el->type == ItemType::LIST_ITEM) {
                if (!dynamic_cast<ListItem *>(el)->deleteByList) {
                    listItemBox->removeWidget(el);
                }
                else {
                    listItemBox->erase(el);
                }
            }
            else {
                listItemBox->erase(el);
            }
        }
    }

} /* namespace gui */

A module-gui/gui/widgets/SideListView.hpp => module-gui/gui/widgets/SideListView.hpp +40 -0
@@ 0,0 1,40 @@
// 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 "BoxLayout.hpp"
#include "InputEvent.hpp"
#include "Label.hpp"
#include "SideListItemProvider.hpp"
#include <apps-common/widgets/BarGraph.hpp>

namespace gui
{
    enum class Order;

    class SideListView : public Rect
    {
      protected:
        static constexpr auto progressbarStartValue = 1;

        std::shared_ptr<SideListItemProvider> provider = nullptr;
        HBarGraph *progressbar                         = nullptr;
        HBox *listItemBox                              = nullptr;

        [[nodiscard]] auto slide(Order order) -> bool;
        auto clear() -> void;

      public:
        SideListView();
        SideListView(Item *parent,
                     unsigned int x,
                     unsigned int y,
                     unsigned int w,
                     unsigned int h,
                     std::shared_ptr<SideListItemProvider> prov);
        ~SideListView();

        auto onInput(const gui::InputEvent &inputEvent) -> bool override;
    };
} /* namespace gui */

M module-gui/gui/widgets/Style.hpp => module-gui/gui/widgets/Style.hpp +41 -0
@@ 235,6 235,47 @@ namespace style

    } // namespace listview

    namespace sidelistview
    {
        inline auto arrow_left_image  = "arrow_left_24px_W_G";
        inline auto arrow_right_image = "arrow_right_24px_W_G";

        namespace arrows_hbox
        {
            inline constexpr auto x = 0U;
            inline constexpr auto y = 150U;
            inline constexpr auto w = window_width;
            inline constexpr auto h = 300U;
        } // namespace arrows_hbox
        namespace list_item
        {
            inline constexpr auto w = window_width;
            inline constexpr auto h = 550U;
        } // namespace list_item
        namespace middle_box
        {
            inline constexpr auto x = 0U;
            inline constexpr auto y = 50U;
            inline constexpr auto w = 480U;
            inline constexpr auto h = 450U;
        } // namespace middle_box
        namespace progress_bar
        {
            inline constexpr auto margin_left   = 0U;
            inline constexpr auto margin_top    = 10U;
            inline constexpr auto margin_right  = 0U;
            inline constexpr auto margin_bottom = 10U;
            inline constexpr auto w             = window_width;
            inline constexpr auto h             = 50U;
        } // namespace progress_bar
        namespace top_message
        {
            inline constexpr auto w    = window_width;
            inline constexpr auto h    = 100U;
            inline constexpr auto font = style::window::font::supersizemelight;
        } // namespace top_message
    }     // namespace sidelistview

    namespace margins
    {
        inline constexpr auto small    = 6U;