~aleteoryx/muditaos

fd89447c8ed617bed1a36b4de9bbb930d5576430 — Przemyslaw Brudny 4 years ago bc6b79f
[BH-924] Added ListViewWithArrows for Bell purposes

Added ListViewWithArrows and ShortOptionWindow for
Bell purposes.
M module-apps/apps-common/options/OptionsList.cpp => module-apps/apps-common/options/OptionsList.cpp +11 -8
@@ 5,28 5,30 @@

namespace gui
{
    OptionsList::OptionsList(std::shared_ptr<OptionsModel> model, std::list<Option> options)
    template <class ListType>
    OptionsList<ListType>::OptionsList(std::shared_ptr<OptionsModel> model, std::list<Option> options)
        : optionsModel{std::move(model)}, options(std::move(options))
    {}

    void OptionsList::createOptions()
    template <class ListType> void OptionsList<ListType>::createOptions()
    {
        optionsModel->createData(options);
    }

    void OptionsList::refreshOptions(std::list<Option> &&optionList)
    template <class ListType> void OptionsList<ListType>::refreshOptions(std::list<Option> &&optionList)
    {
        options = std::move(optionList);
        optionsList->rebuildList(listview::RebuildType::InPlace);
    }

    void OptionsList::refreshOptions(std::list<Option> &&optionList, unsigned int pageIndex)
    template <class ListType>
    void OptionsList<ListType>::refreshOptions(std::list<Option> &&optionList, unsigned int pageIndex)
    {
        options = std::move(optionList);
        optionsList->rebuildList(listview::RebuildType::OnPageElement, pageIndex);
    }

    void OptionsList::addOptions(std::list<Option> &&optionList)
    template <class ListType> void OptionsList<ListType>::addOptions(std::list<Option> &&optionList)
    {
        options = std::move(optionList);
        createOptions();


@@ 34,21 36,22 @@ namespace gui
        optionsList->rebuildList();
    }

    void OptionsList::changeOptions(std::list<Option> &&optionList)
    template <class ListType> void OptionsList<ListType>::changeOptions(std::list<Option> &&optionList)
    {
        clearOptions();
        addOptions(std::move(optionList));
    }

    void OptionsList::recreateOptions()
    template <class ListType> void OptionsList<ListType>::recreateOptions()
    {
        clearOptions();
        createOptions();
    }

    void OptionsList::clearOptions()
    template <class ListType> void OptionsList<ListType>::clearOptions()
    {
        optionsList->clear();
        optionsModel->clearData();
    }

} // namespace gui

M module-apps/apps-common/options/OptionsList.hpp => module-apps/apps-common/options/OptionsList.hpp +6 -2
@@ 7,15 7,16 @@
#include "OptionsModel.hpp"

#include <ListView.hpp>
#include <ListViewWithArrows.hpp>

namespace gui
{
    class OptionsList
    template <class ListType> class OptionsList
    {
      protected:
        explicit OptionsList(std::shared_ptr<OptionsModel>(app), std::list<Option> = {});

        ListView *optionsList                      = nullptr;
        ListType *optionsList                      = nullptr;
        std::shared_ptr<OptionsModel> optionsModel = nullptr;
        std::list<Option> options;



@@ 27,4 28,7 @@ namespace gui
        void refreshOptions(std::list<Option> &&optionList);
        void refreshOptions(std::list<Option> &&optionList, unsigned int pageIndex);
    };

    template class OptionsList<ListView>;
    template class OptionsList<ListViewWithArrows>;
} // namespace gui

M module-apps/apps-common/options/OptionsModel.cpp => module-apps/apps-common/options/OptionsModel.cpp +3 -2
@@ 5,7 5,8 @@
#include "ListView.hpp"
#include "OptionsModel.hpp"

OptionsModel::OptionsModel(app::ApplicationCommon *app) : application(app)
OptionsModel::OptionsModel(app::ApplicationCommon *app, unsigned int minimalItemSpaceRequired)
    : application(app), minimalItemSpaceRequired(minimalItemSpaceRequired)
{}

auto OptionsModel::requestRecordsCount() -> unsigned int


@@ 15,7 16,7 @@ auto OptionsModel::requestRecordsCount() -> unsigned int

auto OptionsModel::getMinimalItemSpaceRequired() const -> unsigned int
{
    return style::window::label::big_h + gui::option::window::option_bottom_margin;
    return minimalItemSpaceRequired;
}

void OptionsModel::requestRecords(const uint32_t offset, const uint32_t limit)

M module-apps/apps-common/options/OptionsModel.hpp => module-apps/apps-common/options/OptionsModel.hpp +6 -2
@@ 10,10 10,14 @@

class OptionsModel : public app::InternalModel<gui::ListItem *>, public gui::ListItemProvider
{
    app::ApplicationCommon *application = nullptr;
  private:
    app::ApplicationCommon *application   = nullptr;
    unsigned int minimalItemSpaceRequired = 0;

  public:
    explicit OptionsModel(app::ApplicationCommon *app);
    explicit OptionsModel(app::ApplicationCommon *app,
                          unsigned int minimalItemSpaceRequired = style::window::label::big_h +
                                                                  gui::option::window::option_bottom_margin);

    void clearData();
    void createData(std::list<gui::Option> &optionList);

M module-apps/apps-common/windows/OptionWindow.hpp => module-apps/apps-common/windows/OptionWindow.hpp +1 -1
@@ 14,7 14,7 @@ namespace gui
    ///  Options GUI window with ListView populated accordingly to provided options in window constructor.
    ///

    class OptionWindow : public AppWindow, protected OptionsList
    class OptionWindow : public AppWindow, protected OptionsList<ListView>
    {
      public:
        OptionWindow(app::ApplicationCommon *app, const std::string &name);

M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +2 -0
@@ 15,6 15,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/ListItem.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItemWithDescription.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListView.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListViewWithArrows.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListViewEngine.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Margins.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Navigation.cpp"


@@ 77,6 78,7 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/ListItemWithDescription.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListItemProvider.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListView.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListViewWithArrows.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/ListViewEngine.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Margins.hpp"
        "${CMAKE_CURRENT_LIST_DIR}/Navigation.hpp"

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

#include "ListViewWithArrows.hpp"
#include "TextFixedSize.hpp"
#include <InputEvent.hpp>

namespace gui
{
    ListViewWithArrows::ListViewWithArrows(Item *parent,
                                           unsigned int x,
                                           unsigned int y,
                                           unsigned int w,
                                           unsigned int h,
                                           std::shared_ptr<ListItemProvider> prov)
        : Rect{parent, x, y, w, h}, ListViewEngine(prov)
    {
        this->setEdges(RectangleEdge::None);
        createLayout();

        body->borderCallback = [this](const InputEvent &inputEvent) -> bool {
            if (!inputEvent.isShortRelease()) {
                return false;
            }
            if (inputEvent.is(KeyCode::KEY_UP) && pageLoaded) {
                return this->requestPreviousPage();
            }
            else if (inputEvent.is(KeyCode::KEY_DOWN) && pageLoaded) {
                return this->requestNextPage();
            }
            else {
                return false;
            }
        };

        focusChangedCallback = [this]([[maybe_unused]] Item &item) -> bool {
            if (focus) {
                setFocus();
            }
            else {
                setFocusItem(nullptr);
            }
            return true;
        };

        body->dimensionChangedCallback = [&](gui::Item &, const BoundingBox &newDim) -> bool {
            if (listOverlay->lastBox->visible && direction == listview::Direction::Top) {
                if (startIndex > 1 && listOverlay->firstBox->visible) {
                    startIndex += 1;
                }

                if (startIndex == 1 && !listOverlay->firstBox->visible) {
                    startIndex = 0;
                }
            }

            currentPageSize = body->getVisibleChildrenCount();
            return true;
        };

        applyScrollCallbacks();

        type = gui::ItemType::LIST;
    }

    void ListViewWithArrows::createLayout()
    {
        widgetBody = new VBox(this, 0, 0, widgetArea.w, widgetArea.h);
        widgetBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        widgetBody->setEdges(RectangleEdge::None);

        listOverlay = new VThreeBox<VBox, VBox, VBox>(widgetBody, 0, 0, 0, 0);
        listOverlay->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        listOverlay->setEdges(RectangleEdge::None);

        listOverlay->firstBox = new VBox(listOverlay);
        listOverlay->firstBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        listOverlay->firstBox->setEdges(RectangleEdge::None);
        listOverlay->firstBox->setVisible(false);

        arrowTop = new ImageBox(listOverlay->firstBox, new Image("bell_arrow_top_W_M"));
        arrowTop->setMinimumSizeToFitImage();

        listOverlay->centerBox = new VBox(listOverlay);
        listOverlay->centerBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
        listOverlay->centerBox->setEdges(RectangleEdge::None);

        body = new VBox(listOverlay->centerBox);
        body->setAlignment(Alignment::Vertical::Top);
        body->setEdges(RectangleEdge::None);

        listOverlay->lastBox = new VBox(listOverlay);
        listOverlay->lastBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        listOverlay->lastBox->setEdges(RectangleEdge::None);
        listOverlay->lastBox->setVisible(false);

        arrowDown = new ImageBox(listOverlay->lastBox, new Image("bell_arrow_down_W_M"));
        arrowDown->setMinimumSizeToFitImage();
    }

    void ListViewWithArrows::applySizeRestrictions(unsigned int w,
                                                   unsigned int h,
                                                   unsigned int outerLayoutsH,
                                                   int outerLayoutsMargin)
    {
        listOverlay->setMinimumSize(w, h);
        body->setMaximumSize(w, h);

        listOverlay->firstBox->setMinimumSize(w, outerLayoutsH);
        listOverlay->firstBox->setMargins(Margins(0, 0, 0, outerLayoutsMargin));
        listOverlay->centerBox->setMaximumSize(w, h);
        listOverlay->lastBox->setMinimumSize(w, outerLayoutsH);
        listOverlay->lastBox->setMargins(Margins(0, outerLayoutsMargin, 0, 0));

        widgetBody->resizeItems();
    }

    void ListViewWithArrows::setListTitle(const std::string &title)
    {
        titleBody = new TextFixedSize(listOverlay->firstBox);
        titleBody->drawUnderline(false);
        titleBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        titleBody->setFont(style::window::font::large);
        titleBody->setMinimumSize(listOverlay->firstBox->widgetMinimumArea.w,
                                  listOverlay->firstBox->widgetMinimumArea.h);
        titleBody->setEdges(RectangleEdge::None);
        titleBody->setEditMode(EditMode::Browse);
        titleBody->setText(title);

        body->setAlignment(Alignment(Alignment::Vertical::Top));
        listOverlay->firstBox->setVisible(true);

        listOverlay->resizeItems();
        // Second resize is needed as we need to first apply max size for center box and next extra margins.
        listOverlay->resizeItems();

        arrowTop->setVisible(false);
        titleBody->setVisible(true);
        listOverlay->firstBox->resizeItems();
    }

    void ListViewWithArrows::applyScrollCallbacks()
    {
        updateScrollCallback = [this](ListViewScrollUpdateData data) {
            auto elementsOnPage = listOverlay->centerBox->widgetArea.h / data.elementMinimalSpaceRequired;

            if (boundaries == Boundaries::Continuous) {
                if (elementsOnPage < data.elementsCount) {
                    listOverlay->firstBox->setVisible(true);
                    listOverlay->lastBox->setVisible(true);
                }
                else {
                    listOverlay->firstBox->setVisible(false);
                    listOverlay->lastBox->setVisible(false);
                }
            }
            else if (boundaries == Boundaries::Fixed) {
                if (elementsOnPage + data.startIndex < data.elementsCount) {
                    listOverlay->lastBox->setVisible(true);
                }
                else {
                    listOverlay->lastBox->setVisible(false);
                }

                if (data.startIndex == 0 && titleBody) {
                    titleBody->setVisible(true);
                    arrowTop->setVisible(false);
                    listOverlay->firstBox->setVisible(true);
                }
                else if (data.startIndex > 1) {
                    if (titleBody) {
                        titleBody->setVisible(false);
                    }
                    arrowTop->setVisible(true);
                    listOverlay->firstBox->setVisible(true);
                }
                else {
                    listOverlay->firstBox->setVisible(false);
                }
            }

            listOverlay->resizeItems();
            // Second resize is needed as we need to first apply max size for center box and next extra margins.
            listOverlay->resizeItems();
        };
    }

    void ListViewWithArrows::setFocus()
    {
        if (!focus) {
            return;
        }
        setFocusItem(body);

        ListViewEngine::setFocus();
    }

    void ListViewWithArrows::setAlignment(const Alignment &value)
    {
        if (body->getAlignment() != value) {
            body->setAlignment(value);
        }
    }

    bool ListViewWithArrows::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
    {
        Rect::onDimensionChanged(oldDim, newDim);
        body->setSize(body->getWidth(), newDim.h);

        return true;
    }

    bool ListViewWithArrows::onInput(const InputEvent &inputEvent)
    {
        return body->onInput(inputEvent);
    }

} /* namespace gui */

A module-gui/gui/widgets/ListViewWithArrows.hpp => module-gui/gui/widgets/ListViewWithArrows.hpp +43 -0
@@ 0,0 1,43 @@
// 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 "ListViewEngine.hpp"
#include "ListItemProvider.hpp"
#include "ThreeBox.hpp"
#include "ImageBox.hpp"
#include "TextFixedSize.hpp"

namespace gui
{
    class ListViewWithArrows : public Rect, public ListViewEngine
    {
      protected:
        VBox *widgetBody                         = nullptr;
        VThreeBox<VBox, VBox, VBox> *listOverlay = nullptr;
        ImageBox *arrowTop                       = nullptr;
        ImageBox *arrowDown                      = nullptr;
        TextFixedSize *titleBody                 = nullptr;

        void createLayout();
        void applyScrollCallbacks();
        void setFocus() override;

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

        void setListTitle(const std::string &title);
        void applySizeRestrictions(unsigned int w, unsigned int h, unsigned int outerLayoutsH, int outerLayoutsMargin);

        void setAlignment(const Alignment &value) override;
        bool onInput(const InputEvent &inputEvent) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
    };

} /* namespace gui */

M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +3 -1
@@ 21,6 21,7 @@ target_sources(application-bell-common
        src/widgets/ListItems.cpp

        src/options/BellOptionWindow.cpp
        src/options/BellShortOptionWindow.cpp
        src/options/OptionBellMenu.cpp
    PUBLIC
        include/common/BellFinishedWindow.hpp


@@ 35,6 36,7 @@ target_sources(application-bell-common
        include/common/widgets/BellSideListItemWithCallbacks.hpp
        include/common/widgets/ListItems.hpp
        include/common/options/BellOptionWindow.hpp
        include/common/options/BellShortOptionWindow.hpp
        include/common/options/OptionBellMenu.hpp
)



@@ 45,7 47,7 @@ target_link_libraries(application-bell-common

    PRIVATE
        bell::app-main
        bell::app-alarm 
        bell::app-alarm
        module-gui
        service-time
        bell::db

M products/BellHybrid/apps/common/include/common/options/BellOptionWindow.hpp => products/BellHybrid/apps/common/include/common/options/BellOptionWindow.hpp +2 -6
@@ 6,26 6,22 @@
#include <ApplicationCommon.hpp>
#include <AppWindow.hpp>
#include <OptionsList.hpp>
#include <ThreeBox.hpp>

namespace style::bell_options_list
{
    inline constexpr auto w                    = 380U;
    inline constexpr auto center_layout_h      = 400U;
    inline constexpr auto h                    = 400U;
    inline constexpr auto outer_layouts_h      = 64U;
    inline constexpr auto outer_layouts_margin = 7U;
} // namespace style::bell_options_list

namespace gui
{
    class BellOptionWindow : public AppWindow, protected OptionsList
    class BellOptionWindow : public AppWindow, protected OptionsList<ListViewWithArrows>
    {
      public:
        BellOptionWindow(app::ApplicationCommon *app, const std::string &name);

        VThreeBox<VBox, VBox, VBox> *body = nullptr;
        void setListTitle(const std::string &title);
        void createLayout();

        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void onClose(CloseReason reason) override;

A products/BellHybrid/apps/common/include/common/options/BellShortOptionWindow.hpp => products/BellHybrid/apps/common/include/common/options/BellShortOptionWindow.hpp +27 -0
@@ 0,0 1,27 @@
// 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 <ApplicationCommon.hpp>
#include <AppWindow.hpp>
#include <OptionsList.hpp>
#include <apps-common/widgets/BellBaseLayout.hpp>

namespace gui
{
    class BellShortOptionWindow : public AppWindow, protected OptionsList<ListView>
    {
      private:
        BellBaseLayout *body{};

      public:
        BellShortOptionWindow(app::ApplicationCommon *app, const std::string &name);
        void setListTitle(const std::string &title);

        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void onClose(CloseReason reason) override;
        void rebuild() override;
        void buildInterface() override;
    };
}; // namespace gui

M products/BellHybrid/apps/common/src/options/BellOptionWindow.cpp => products/BellHybrid/apps/common/src/options/BellOptionWindow.cpp +10 -54
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "common/options/BellOptionWindow.hpp"
#include "common/options/OptionBellMenu.hpp"

#include <messages/OptionsWindow.hpp>
#include <TextFixedSize.hpp>


@@ 9,7 10,8 @@
namespace gui
{
    BellOptionWindow::BellOptionWindow(app::ApplicationCommon *app, const std::string &name)
        : AppWindow(app, name), OptionsList(std::make_shared<OptionsModel>(app))
        : AppWindow(app, name), OptionsList(std::make_shared<OptionsModel>(
                                    app, style::bell_options::h + 2 * style::bell_options::option_margin))
    {
        buildInterface();
    }


@@ 27,68 29,22 @@ namespace gui
        header->setTitleVisibility(false);
        bottomBar->setVisible(false);

        createLayout();

        optionsList = new gui::ListView(body->centerBox, 0, 0, 0, 0, optionsModel, listview::ScrollBarType::None);
        optionsList->setAlignment(Alignment(Alignment::Vertical::Center));
        optionsList->setMaximumSize(style::bell_options_list::w, style::bell_options_list::center_layout_h);

        body->centerBox->resizeItems();
        optionsList = new gui::ListViewWithArrows(this, 0, 0, style::window_width, style::window_height, optionsModel);
        optionsList->setAlignment(Alignment(Alignment::Vertical::Top));
        optionsList->applySizeRestrictions(style::bell_options_list::w,
                                           style::bell_options_list::h,
                                           style::bell_options_list::outer_layouts_h,
                                           style::bell_options_list::outer_layouts_margin);

        optionsList->prepareRebuildCallback = [this]() { recreateOptions(); };

        optionsModel->createData(options);

        setFocusItem(optionsList);
    }

    void BellOptionWindow::createLayout()
    {
        auto windowBody = new VBox(this, 0, 0, style::window_width, style::window_height);
        windowBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));

        body = new VThreeBox<VBox, VBox, VBox>(
            windowBody, 0, 0, style::bell_options_list::w, style::bell_options_list::center_layout_h);
        body->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        body->setEdges(RectangleEdge::None);

        body->firstBox = new VBox(body);
        body->firstBox->setMinimumSize(style::bell_options_list::w, style::bell_options_list::outer_layouts_h);
        body->firstBox->setMargins(Margins(0, 0, 0, style::bell_options_list::outer_layouts_margin));
        body->firstBox->setAlignment(Alignment(Alignment::Vertical::Top));
        body->firstBox->setEdges(RectangleEdge::None);
        body->firstBox->setVisible(false);

        body->centerBox = new VBox(body);
        body->centerBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
        body->centerBox->setMaximumSize(style::bell_options_list::w, style::bell_options_list::center_layout_h);
        body->centerBox->setEdges(RectangleEdge::None);

        body->lastBox = new VBox(body);
        body->lastBox->setMinimumSize(style::bell_options_list::w, style::bell_options_list::outer_layouts_h);
        body->lastBox->setMargins(Margins(0, style::bell_options_list::outer_layouts_margin, 0, 0));
        body->lastBox->setAlignment(Alignment(Alignment::Vertical::Top));
        body->lastBox->setEdges(RectangleEdge::None);
        body->lastBox->setVisible(false);
    }

    void BellOptionWindow::setListTitle(const std::string &title)
    {
        auto titleBody = new TextFixedSize(body->firstBox);
        titleBody->drawUnderline(false);
        titleBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        titleBody->setFont(style::window::font::large);
        titleBody->setMinimumSize(style::bell_options_list::w, style::bell_options_list::outer_layouts_h);
        titleBody->setEdges(RectangleEdge::None);
        titleBody->setEditMode(EditMode::Browse);
        titleBody->setText(title);

        optionsList->setAlignment(Alignment(Alignment::Vertical::Top));
        body->firstBox->setVisible(true);

        body->resizeItems();
        // Second resize is needed as we need to first apply max size for center box and next extra margins.
        body->resizeItems();
        optionsList->setListTitle(title);
    }

    void BellOptionWindow::onClose([[maybe_unused]] CloseReason reason)

A products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp => products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp +75 -0
@@ 0,0 1,75 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "common/options/BellShortOptionWindow.hpp"
#include "common/options/OptionBellMenu.hpp"

#include <messages/OptionsWindow.hpp>
#include <TextFixedSize.hpp>

namespace gui
{
    BellShortOptionWindow::BellShortOptionWindow(app::ApplicationCommon *app, const std::string &name)
        : AppWindow(app, name), OptionsList(std::make_shared<OptionsModel>(
                                    app, style::bell_options::h + 2 * style::bell_options::option_margin))
    {
        buildInterface();
    }

    void BellShortOptionWindow::rebuild()
    {
        recreateOptions();
    }

    void BellShortOptionWindow::buildInterface()
    {
        AppWindow::buildInterface();

        statusBar->setVisible(false);
        header->setTitleVisibility(false);
        bottomBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, false);

        optionsList = new gui::ListView(body->centerBox, 0, 0, 0, 0, optionsModel, listview::ScrollBarType::None);
        optionsList->setAlignment(Alignment(Alignment::Vertical::Bottom));
        optionsList->setMinimumSize(style::bell_options::default_text_width, style::bell_base_layout::center_layout_h);
        optionsList->setEdges(RectangleEdge::None);

        body->resize();

        optionsList->prepareRebuildCallback = [this]() { recreateOptions(); };
        optionsModel->createData(options);

        setFocusItem(optionsList);
    }

    void BellShortOptionWindow::setListTitle(const std::string &title)
    {
        auto titleBody = new TextFixedSize(body->firstBox);
        titleBody->drawUnderline(false);
        titleBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        titleBody->setFont(style::window::font::largelight);
        titleBody->setMinimumSize(style::bell_base_layout::outer_layouts_w, style::bell_base_layout::outer_layouts_h);
        titleBody->setEdges(RectangleEdge::None);
        titleBody->setEditMode(EditMode::Browse);
        titleBody->setRichText(title);

        body->firstBox->resizeItems();
    }

    void BellShortOptionWindow::onClose([[maybe_unused]] CloseReason reason)
    {
        optionsList->onClose();
    }

    void BellShortOptionWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (auto message = dynamic_cast<gui::OptionsWindowOptions *>(data)) {
            LOG_DEBUG("Options load!");
            options = message->takeOptions();
        }

        optionsList->rebuildList(listview::RebuildType::InPlace);
    }
} /* namespace gui */