From 6d344fe6cb6df6fc0ce4d83d2a6c88f078b20677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jo=C5=84ski?= Date: Mon, 12 Jul 2021 07:01:23 +0200 Subject: [PATCH] [BH-655] Add SideListView Add view commonly used in Bell - SideListView. --- module-gui/gui/widgets/CMakeLists.txt | 7 + .../gui/widgets/ListItemWithDescription.cpp | 17 +++ .../gui/widgets/ListItemWithDescription.hpp | 20 +++ module-gui/gui/widgets/SideListItem.cpp | 24 +++ module-gui/gui/widgets/SideListItem.hpp | 18 +++ .../gui/widgets/SideListItemProvider.hpp | 25 ++++ module-gui/gui/widgets/SideListView.cpp | 140 ++++++++++++++++++ module-gui/gui/widgets/SideListView.hpp | 40 +++++ module-gui/gui/widgets/Style.hpp | 41 +++++ 9 files changed, 332 insertions(+) create mode 100644 module-gui/gui/widgets/ListItemWithDescription.cpp create mode 100644 module-gui/gui/widgets/ListItemWithDescription.hpp create mode 100644 module-gui/gui/widgets/SideListItem.cpp create mode 100644 module-gui/gui/widgets/SideListItem.hpp create mode 100644 module-gui/gui/widgets/SideListItemProvider.hpp create mode 100644 module-gui/gui/widgets/SideListView.cpp create mode 100644 module-gui/gui/widgets/SideListView.hpp diff --git a/module-gui/gui/widgets/CMakeLists.txt b/module-gui/gui/widgets/CMakeLists.txt index 2ca64c9521bf5769146db841501aaeb70775bf6d..24f53b37e8ebb1f38a9f0f8807b17ef9cc621dfa 100644 --- a/module-gui/gui/widgets/CMakeLists.txt +++ b/module-gui/gui/widgets/CMakeLists.txt @@ -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" diff --git a/module-gui/gui/widgets/ListItemWithDescription.cpp b/module-gui/gui/widgets/ListItemWithDescription.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bebefab93bb45db30c74068e0e95efad6a2b0e02 --- /dev/null +++ b/module-gui/gui/widgets/ListItemWithDescription.cpp @@ -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 diff --git a/module-gui/gui/widgets/ListItemWithDescription.hpp b/module-gui/gui/widgets/ListItemWithDescription.hpp new file mode 100644 index 0000000000000000000000000000000000000000..89d0d56fb2efcaf2cf71410fc81a532fdebc5725 --- /dev/null +++ b/module-gui/gui/widgets/ListItemWithDescription.hpp @@ -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 */ diff --git a/module-gui/gui/widgets/SideListItem.cpp b/module-gui/gui/widgets/SideListItem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d017bcdbd68fba0389e0c4e53ae201212f98d64b --- /dev/null +++ b/module-gui/gui/widgets/SideListItem.cpp @@ -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 */ diff --git a/module-gui/gui/widgets/SideListItem.hpp b/module-gui/gui/widgets/SideListItem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2ce046e447ed45b2fbcfd4b81ea269be5ba854b6 --- /dev/null +++ b/module-gui/gui/widgets/SideListItem.hpp @@ -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 */ diff --git a/module-gui/gui/widgets/SideListItemProvider.hpp b/module-gui/gui/widgets/SideListItemProvider.hpp new file mode 100644 index 0000000000000000000000000000000000000000..58b3f06d24d1b0698b49fe9bcc60a8f9cb5f8953 --- /dev/null +++ b/module-gui/gui/widgets/SideListItemProvider.hpp @@ -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 diff --git a/module-gui/gui/widgets/SideListView.cpp b/module-gui/gui/widgets/SideListView.cpp new file mode 100644 index 0000000000000000000000000000000000000000..724094a503cd05e7f3c011d60bf4a74c612a3dac --- /dev/null +++ b/module-gui/gui/widgets/SideListView.cpp @@ -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 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(el)->deleteByList) { + listItemBox->removeWidget(el); + } + else { + listItemBox->erase(el); + } + } + else { + listItemBox->erase(el); + } + } + } + +} /* namespace gui */ diff --git a/module-gui/gui/widgets/SideListView.hpp b/module-gui/gui/widgets/SideListView.hpp new file mode 100644 index 0000000000000000000000000000000000000000..55d92195ad413023ad0ce2a0fb82de41988cb875 --- /dev/null +++ b/module-gui/gui/widgets/SideListView.hpp @@ -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 + +namespace gui +{ + enum class Order; + + class SideListView : public Rect + { + protected: + static constexpr auto progressbarStartValue = 1; + + std::shared_ptr 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 prov); + ~SideListView(); + + auto onInput(const gui::InputEvent &inputEvent) -> bool override; + }; +} /* namespace gui */ diff --git a/module-gui/gui/widgets/Style.hpp b/module-gui/gui/widgets/Style.hpp index a1b998772c82153a7fa617b37037e4e171f864b3..8fa588071ecf6806d7c5c6fb5a393a45b0177809 100644 --- a/module-gui/gui/widgets/Style.hpp +++ b/module-gui/gui/widgets/Style.hpp @@ -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;