~aleteoryx/muditaos

64db7d832702afe7a34ce8318c69aa1ca53688eb — Adam 5 years ago 1a6ea1f
EDG-3585 Small fixup for refresh & cleanup in buildDrawLists (#916)

* EGD-3585 Minor refresh fixup&  Normalised buildDrawList everywhere
54 files changed, 242 insertions(+), 473 deletions(-)

M changelog.md
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/WindowsStack.hpp
M module-apps/application-desktop/windows/DesktopMainWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.hpp
M module-apps/messages/AppMessage.hpp
M module-apps/windows/AppWindow.cpp
M module-apps/windows/AppWindow.hpp
M module-gui/gui/Common.hpp
M module-gui/gui/core/DrawCommand.hpp
A module-gui/gui/core/DrawCommandForward.hpp
M module-gui/gui/core/RawFont.cpp
M module-gui/gui/core/Renderer.cpp
M module-gui/gui/core/Renderer.hpp
M module-gui/gui/widgets/Arc.cpp
M module-gui/gui/widgets/Arc.hpp
M module-gui/gui/widgets/BottomBar.hpp
M module-gui/gui/widgets/BoxLayout.cpp
M module-gui/gui/widgets/BoxLayout.hpp
M module-gui/gui/widgets/CMakeLists.txt
M module-gui/gui/widgets/CheckBox.hpp
M module-gui/gui/widgets/Circle.cpp
M module-gui/gui/widgets/Circle.hpp
M module-gui/gui/widgets/GridLayout.hpp
M module-gui/gui/widgets/Image.cpp
M module-gui/gui/widgets/Image.hpp
M module-gui/gui/widgets/Item.cpp
M module-gui/gui/widgets/Item.hpp
D module-gui/gui/widgets/KeyEvent.hpp
M module-gui/gui/widgets/Label.cpp
M module-gui/gui/widgets/Label.hpp
D module-gui/gui/widgets/Layout.cpp
M module-gui/gui/widgets/ListView.cpp
M module-gui/gui/widgets/ListView.hpp
M module-gui/gui/widgets/ProgressBar.cpp
M module-gui/gui/widgets/ProgressBar.hpp
M module-gui/gui/widgets/Rect.cpp
M module-gui/gui/widgets/Rect.hpp
M module-gui/gui/widgets/RichTextParser.cpp
M module-gui/gui/widgets/Span.hpp
M module-gui/gui/widgets/Text.cpp
M module-gui/gui/widgets/Text.hpp
M module-gui/gui/widgets/TopBar.cpp
M module-gui/gui/widgets/TopBar.hpp
M module-gui/gui/widgets/Window.cpp
M module-gui/gui/widgets/Window.hpp
M module-gui/test/test-catch/test-gui.cpp
M module-services/service-gui/ServiceGUI.cpp
M module-services/service-gui/ServiceGUI.hpp
M module-services/service-gui/WorkerGUI.cpp
M module-services/service-gui/messages/DrawMessage.cpp
M module-services/service-gui/messages/DrawMessage.hpp
M source/MessageType.hpp
M changelog.md => changelog.md +1 -0
@@ 21,6 21,7 @@
* `[desktop][messages]` Fixed notifications display and navigation
* `[cellular]` Fixed 32 bit UCS2 codes handling.
* `[call]` Fixed incorrect start of call duration timer
* `[GUI]` minor refresh race fixed

### Other


M module-apps/Application.cpp => module-apps/Application.cpp +38 -50
@@ 74,6 74,10 @@ namespace app

        longPressTimer = std::make_unique<sys::Timer>("LongPress", this, key_timer_ms);
        longPressTimer->connect([&](sys::Timer &) { longPressTimerCallback(); });

        connect(typeid(AppRefreshMessage), [this](sys::DataMessage *msg, sys::ResponseMessage *) -> sys::Message_t {
            return handleAppRefresh(msg);
        });
    }

    Application::~Application() = default;


@@ 108,43 112,32 @@ namespace app

    void Application::render(gui::RefreshModes mode)
    {
        if (getCurrentWindow() == nullptr) {
        if (windowsStack.isEmpty()) {
            LOG_ERROR("Current window is not defined");
            return;
        }

        LOG_DEBUG("Rendering %s", getCurrentWindow()->getName().c_str());

        // send drawing commands only when if application is in active and visible.
        if (state == State::ACTIVE_FORGROUND) {
            auto currwin = getCurrentWindow();
            auto window = getCurrentWindow();
            if (Store::Battery::get().state == Store::Battery::State::Charging) {
                currwin->batteryCharging(true);
                window->batteryCharging(true);
            }
            else {
                currwin->updateBatteryLevel(Store::Battery::get().level);
                window->updateBatteryLevel(Store::Battery::get().level);
            }
            currwin->setSIM();
            currwin->updateSignalStrength();
            currwin->updateNetworkAccessTechnology();

            std::list<gui::DrawCommand *> commandsList = currwin->buildDrawList();
            window->setSIM();
            window->updateSignalStrength();
            window->updateNetworkAccessTechnology();

            auto message = std::make_shared<sgui::DrawMessage>(window->buildDrawList(), mode);
            if (shutdownInProgress) {
                auto msg =
                    std::make_shared<sgui::DrawMessage>(commandsList, mode, sgui::DrawMessage::DrawCommand::SHUTDOWN);
                sys::Bus::SendUnicast(msg, "ServiceGUI", this);
                message->setCommandType(sgui::DrawMessage::Type::SHUTDOWN);
            }
            else if (suspendInProgress) {
                auto msg =
                    std::make_shared<sgui::DrawMessage>(commandsList, mode, sgui::DrawMessage::DrawCommand::SUSPEND);
                sys::Bus::SendUnicast(msg, "ServiceGUI", this);
            }
            else {
                auto msg =
                    std::make_shared<sgui::DrawMessage>(commandsList, mode, sgui::DrawMessage::DrawCommand::NORMAL);
                sys::Bus::SendUnicast(msg, "ServiceGUI", this);
                message->setCommandType(sgui::DrawMessage::Type::SUSPEND);
            }
            sys::Bus::SendUnicast(message, "ServiceGUI", this);
        }

        if (suspendInProgress)


@@ 197,8 190,10 @@ namespace app

    void Application::refreshWindow(gui::RefreshModes mode)
    {
        auto msg = std::make_shared<AppRefreshMessage>(mode);
        sys::Bus::SendUnicast(msg, this->GetName(), this);
        if (not windowsStack.isEmpty()) {
            auto msg = std::make_shared<AppRefreshMessage>(mode, getCurrentWindow()->getName());
            sys::Bus::SendUnicast(msg, this->GetName(), this);
        }
    }

    sys::Message_t Application::DataReceivedHandler(sys::DataMessage *msgl)


@@ 239,9 234,6 @@ namespace app
        else if (msgl->messageType == MessageType::AppRebuild) {
            return handleAppRebuild(msg);
        }
        else if (msgl->messageType == MessageType::AppRefresh) {
            return handleAppRefresh(msgl);
        }
        else if (msgl->messageType == MessageType::AppFocusLost) {
            return handleAppFocusLost(msgl);
        }


@@ 282,7 274,7 @@ namespace app
        else if (msg->getEvent().state == gui::InputEvent::State::keyReleasedShort) {
            longPressTimer->stop();
        }
        if (getCurrentWindow() != nullptr && getCurrentWindow()->onInput(msg->getEvent())) {
        if (not windowsStack.isEmpty() && getCurrentWindow()->onInput(msg->getEvent())) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();


@@ 397,25 389,23 @@ namespace app
            if (switchData && switchData->ignoreCurrentWindowOnStack) {
                popToWindow(getPrevWindow());
            }
            getCurrentWindow()->onClose();
            if (not windowsStack.isEmpty()) {
                getCurrentWindow()->onClose();
            }
            setActiveWindow(msg->getWindowName());
            LOG_DEBUG("Current window: %s vs %s", getCurrentWindow()->getName().c_str(), msg->getWindowName().c_str());
            getCurrentWindow()->handleSwitchData(switchData.get());

            // check if this is case where application is returning to the last visible window.
            if ((switchData != nullptr) && (msg->LastSeenWindow)) {}
            else {
                auto ret = dynamic_cast<gui::SwitchSpecialChar *>(switchData.get());
                if (ret != nullptr && switchData != nullptr) {
                    auto text = dynamic_cast<gui::Text *>(getCurrentWindow()->getFocusItem());
                    if (text != nullptr) {
                        text->addText(ret->getDescription());
                        refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                        return msgHandled();
                    }
            auto ret = dynamic_cast<gui::SwitchSpecialChar *>(switchData.get());
            if (ret != nullptr && switchData != nullptr) {
                auto text = dynamic_cast<gui::Text *>(getCurrentWindow()->getFocusItem());
                if (text != nullptr) {
                    text->addText(ret->getDescription());
                    refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                    return msgHandled();
                }
                getCurrentWindow()->onBeforeShow(msg->getCommand(), switchData.get());
            }
            getCurrentWindow()->onBeforeShow(msg->getCommand(), switchData.get());
            refreshWindow(gui::RefreshModes::GUI_REFRESH_DEEP);
        }
        else {


@@ 449,6 439,13 @@ namespace app
    sys::Message_t Application::handleAppRefresh(sys::DataMessage *msgl)
    {
        auto *msg = static_cast<AppRefreshMessage *>(msgl);
        assert(msg);
        if (windowsStack.isEmpty() || (getCurrentWindow()->getName() != msg->getWindowName())) {
            LOG_DEBUG("Ignore request for window %s we are on window %s",
                      msg->getWindowName().c_str(),
                      windowsStack.isEmpty() ? "none" : getCurrentWindow()->getName().c_str());
            return msgNotHandled();
        }
        render(msg->getMode());
        return msgHandled();
    }


@@ 518,15 515,6 @@ namespace app
        sys::Bus::SendUnicast(msg, application, sender);
    }

    void Application::messageRefreshApplication(sys::Service *sender,
                                                std::string application,
                                                std::string window,
                                                gui::SwitchData *data)
    {
        auto msg = std::make_shared<AppMessage>(MessageType::AppRefresh);
        sys::Bus::SendUnicast(msg, application, sender);
    }

    void Application::messageCloseApplication(sys::Service *sender, std::string application)
    {


M module-apps/Application.hpp => module-apps/Application.hpp +1 -4
@@ 291,10 291,6 @@ namespace app
                                             std::string application,
                                             std::string window,
                                             std::unique_ptr<gui::SwitchData> data);
        static void messageRefreshApplication(sys::Service *sender,
                                              std::string application,
                                              std::string window,
                                              gui::SwitchData *data = nullptr);
        static void messageCloseApplication(sys::Service *sender, std::string application);
        static void messageRebuildApplication(sys::Service *sender, std::string application);
        static void messageApplicationLostFocus(sys::Service *sender, std::string application);


@@ 328,6 324,7 @@ namespace app
        /// @ingrup AppWindowStack
        void cleanPrevWindw();
        /// getter for current wisible window in application
        /// if there is none - returns default window
        /// @ingrup AppWindowStack
        gui::AppWindow *getCurrentWindow();


M module-apps/WindowsStack.hpp => module-apps/WindowsStack.hpp +5 -0
@@ 51,5 51,10 @@ namespace app
            auto ret = windows.find(name);
            return ret == std::end(windows) ? nullptr : ret->second.get();
        }

        [[nodiscard]] auto isEmpty() const noexcept
        {
            return stack.size() == 0;
        }
    };
} // namespace app

M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +6 -7
@@ 78,6 78,12 @@ namespace gui
    DesktopMainWindow::DesktopMainWindow(app::Application *app) : AppWindow(app, app::window::name::desktop_main_window)
    {
        buildInterface();

        preBuildDrawListHook = [this](std::list<Command> &cmd) {
            if (time != nullptr) {
                time->setText(topBar->getTimeString());
            }
        };
    }

    void DesktopMainWindow::setVisibleState()


@@ 146,7 152,6 @@ namespace gui
        if (inputEvent.is(KeyCode::KEY_PND) && (!app->lockHandler.lock.isLocked())) {
            app->lockHandler.lock.lock();
            setVisibleState();
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            application->setSuspendFlag(true);
            return true;
        }


@@ 249,12 254,6 @@ namespace gui
        return ret;
    }

    std::list<DrawCommand *> DesktopMainWindow::buildDrawList()
    {
        time->setText(topBar->getTimeString());
        return gui::AppWindow::buildDrawList();
    }

    auto DesktopMainWindow::buildNotifications(app::ApplicationDesktop *app) -> bool
    {
        erase(notifications);

M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +0 -1
@@ 83,7 83,6 @@ namespace gui
        void destroyInterface() override;
        bool updateTime(const UTF8 &timeStr) override;
        bool updateTime(const uint32_t &timestamp, bool mode24H) override;
        std::list<DrawCommand *> buildDrawList() override;

      private:
        void invalidate() noexcept;

M module-apps/messages/AppMessage.hpp => module-apps/messages/AppMessage.hpp +13 -10
@@ 1,9 1,9 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#ifndef MODULE_APPS_MESSAGES_APPMESSAGE_HPP_
#define MODULE_APPS_MESSAGES_APPMESSAGE_HPP_
#pragma once

#include "Common.hpp"
#include "MessageType.hpp"
#include "Service/Message.hpp"
#include "SwitchData.hpp"


@@ 21,7 21,7 @@ namespace app
    {
      public:
        AppMessage(MessageType messageType) : sys::DataMessage(messageType){};
        virtual ~AppMessage(){};
        AppMessage() : sys::DataMessage(MessageType::AppMessage){};
    };

    // this message is used to notify application about switching event. Application will gain or lose focus upon


@@ 80,16 80,21 @@ namespace app
    {
      protected:
        gui::RefreshModes mode;
        std::string window_name;

      public:
        //	AppRefreshMessage( const std::string& application, gui::RefreshModes mode ) :
        AppRefreshMessage(gui::RefreshModes mode) : AppMessage(MessageType::AppRefresh), mode{mode} {};
        virtual ~AppRefreshMessage(){};
        AppRefreshMessage(gui::RefreshModes mode, std::string window_name)
            : mode{mode}, window_name(std::move(window_name)){};

        const gui::RefreshModes &getMode()
        [[nodiscard]] const gui::RefreshModes &getMode() const
        {
            return mode;
        };
        }

        [[nodiscard]] const std::string &getWindowName() const
        {
            return window_name;
        }
    };

    class AppSwitchWindowMessage : public AppMessage


@@ 101,7 106,6 @@ namespace app
        std::unique_ptr<gui::SwitchData> data;

      public:
        bool LastSeenWindow      = false;
        AppSwitchWindowMessage() = delete;

        AppSwitchWindowMessage(const std::string &window,


@@ 170,4 174,3 @@ namespace app
        {}
    };
};     // namespace app
#endif /* MODULE_APPS_MESSAGES_APPMESSAGE_HPP_ */

M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +0 -5
@@ 118,11 118,6 @@ namespace gui
        }
    }

    std::list<DrawCommand *> AppWindow::buildDrawList()
    {
        return Window::buildDrawList();
    }

    bool AppWindow::onDatabaseMessage(sys::Message *msg)
    {
        return false;

M module-apps/windows/AppWindow.hpp => module-apps/windows/AppWindow.hpp +0 -1
@@ 77,7 77,6 @@ namespace gui
        void buildInterface() override;
        void destroyInterface() override;
        bool onInput(const InputEvent &inputEvent) override;
        std::list<DrawCommand *> buildDrawList() override;
        /// Setting bottom bar temporary text
        /// @param text - bottomBar text
        /// @param overwriteOthers - set or not other bottomBar texts to "" (default true)

M module-gui/gui/Common.hpp => module-gui/gui/Common.hpp +11 -0
@@ 143,3 143,14 @@ namespace gui
    void setTimeFunction(timeSecondsFunctionPtr fptr);

} // namespace gui

inline const char *c_str(gui::RefreshModes refresh)
{
    switch (refresh) {
    case gui::RefreshModes::GUI_REFRESH_FAST:
        return "GUI_REFRESH_FAST";
    case gui::RefreshModes::GUI_REFRESH_DEEP:
        return "GUI_REFRESH_DEEP";
    }
    return "";
}

M module-gui/gui/core/DrawCommand.hpp => module-gui/gui/core/DrawCommand.hpp +0 -9
@@ 15,9 15,6 @@
namespace gui
{

    /**
     * @brief IDs of the drawing commands
     */
    enum class DrawCommandID
    {
        GUI_DRAW_UNDEFINED = 0,


@@ 50,9 47,6 @@ namespace gui
        virtual ~DrawCommand(){};
    };

    /**
     * @brief Draw command for rendering.
     */
    class CommandRender : public DrawCommand
    {
      public:


@@ 63,9 57,6 @@ namespace gui
        };
    };

    /**
     * @brief Draw command for line.
     */
    class CommandLine : public DrawCommand
    {
      public:

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

#pragma once

#include <memory>

namespace gui
{
    class DrawCommand;

    using Command = std::unique_ptr<DrawCommand>;
} // namespace gui

M module-gui/gui/core/RawFont.cpp => module-gui/gui/core/RawFont.cpp +4 -3
@@ 12,7 12,6 @@
#include "utf8/UTF8.hpp"     // for UTF8
#include <cstring>           // for memcpy
#include <utility>           // for pair
#include <vector>            // for vector

namespace gui
{


@@ 307,7 306,8 @@ namespace gui
        commandRect->penWidth = unsupported->xoffset;

        auto renderCtx                           = std::make_unique<Context>(unsupported->width, unsupported->height);
        std::vector<gui::DrawCommand *> commands = {commandRect.get()};
        std::list<Command> commands;
        commands.emplace_back(std::move(commandRect));
        Renderer().render(renderCtx.get(), commands);

        auto size         = unsupported->width * unsupported->height;


@@ 317,7 317,8 @@ namespace gui

    void RawFont::setFallbackFont(RawFont *fallback)
    {
        if (fallback != this)
        if (fallback != this) {
            fallback_font = fallback;
        }
    }
} /* namespace gui */

M module-gui/gui/core/Renderer.cpp => module-gui/gui/core/Renderer.cpp +14 -8
@@ 288,30 288,36 @@ namespace gui
        delete drawCtx;
    }

    void Renderer::render(Context *ctx, std::vector<DrawCommand *> &commands)
    void Renderer::render(Context *ctx, std::list<Command> &commands)
    {
        for (auto cmd : commands) {
        if (ctx == nullptr) {
            return;
        }
        for (auto &cmd : commands) {
            if (cmd == nullptr) {
                continue;
            }
            switch (cmd->id) {
            case DrawCommandID::GUI_DRAW_CLEAR:
                ctx->fill(15);
                break;
            case DrawCommandID::GUI_DRAW_LINE:
                drawLine(ctx, static_cast<CommandLine *>(cmd));
                drawLine(ctx, static_cast<CommandLine *>(cmd.get()));
                break;
            case DrawCommandID::GUI_DRAW_RECT:
                drawRectangle(ctx, static_cast<CommandRectangle *>(cmd));
                drawRectangle(ctx, static_cast<CommandRectangle *>(cmd.get()));
                break;
            case DrawCommandID::GUI_DRAW_ARC:
                drawArc(ctx, static_cast<CommandArc *>(cmd));
                drawArc(ctx, static_cast<CommandArc *>(cmd.get()));
                break;
            case DrawCommandID::GUI_DRAW_CIRCLE:
                drawCircle(ctx, static_cast<CommandCircle *>(cmd));
                drawCircle(ctx, static_cast<CommandCircle *>(cmd.get()));
                break;
            case DrawCommandID::GUI_DRAW_TEXT:
                drawText(ctx, static_cast<CommandText *>(cmd));
                drawText(ctx, static_cast<CommandText *>(cmd.get()));
                break;
            case DrawCommandID::GUI_DRAW_IMAGE:
                drawImage(ctx, static_cast<CommandImage *>(cmd));
                drawImage(ctx, static_cast<CommandImage *>(cmd.get()));
                break;
            default:
                break;

M module-gui/gui/core/Renderer.hpp => module-gui/gui/core/Renderer.hpp +3 -2
@@ 3,12 3,13 @@

#pragma once

#include <vector>
#include <list>

#include <module-utils/math/Math.hpp>

#include "DrawCommand.hpp"
#include "Context.hpp"
#include "DrawCommandForward.hpp"

namespace gui
{


@@ 49,7 50,7 @@ namespace gui
      public:
        virtual ~Renderer() = default;

        void render(Context *ctx, std::vector<DrawCommand *> &commands);
        void render(Context *ctx, std::list<Command> &commands);
    };

} /* namespace gui */

M module-gui/gui/widgets/Arc.cpp => module-gui/gui/widgets/Arc.cpp +3 -12
@@ 104,23 104,14 @@ namespace gui
        return start;
    }

    std::list<DrawCommand *> Arc::buildDrawList()
    void Arc::buildDrawListImplementation(std::list<Command> &commands)
    {
        if (!visible) {
            return {};
        }

        auto arc   = new CommandArc(center, radius, start, sweep, focus ? focusPenWidth : penWidth, color);
        auto arc = std::make_unique<CommandArc>(center, radius, start, sweep, focus ? focusPenWidth : penWidth, color);
        arc->areaX = widgetArea.x;
        arc->areaY = widgetArea.y;
        arc->areaW = widgetArea.w;
        arc->areaH = widgetArea.h;

        std::list<DrawCommand *> commands;
        commands.push_back(arc);

        auto childrenCommands = Item::buildChildrenDrawList();
        commands.splice(commands.end(), childrenCommands);
        return commands;
        commands.emplace_back(std::move(arc));
    }
} // namespace gui

M module-gui/gui/widgets/Arc.hpp => module-gui/gui/widgets/Arc.hpp +1 -1
@@ 47,7 47,7 @@ namespace gui
        trigonometry::Degrees getSweepAngle() const noexcept;
        trigonometry::Degrees getStartAngle() const noexcept;

        std::list<DrawCommand *> buildDrawList() override;
        void buildDrawListImplementation(std::list<Command> &commands) override;

      protected:
        Arc(Item *parent,

M module-gui/gui/widgets/BottomBar.hpp => module-gui/gui/widgets/BottomBar.hpp +1 -2
@@ 83,8 83,7 @@ namespace gui

        void setFont(Side side, const UTF8 &fontName);

        // virtual methods from Item
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim);
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
    };

} /* namespace gui */

M module-gui/gui/widgets/BoxLayout.cpp => module-gui/gui/widgets/BoxLayout.cpp +0 -6
@@ 100,12 100,6 @@ namespace gui
        Item::erase();
    }

    std::list<DrawCommand *> BoxLayout::buildDrawList()
    {
        auto el = Rect::buildDrawList();
        return el;
    }

    void BoxLayout::setVisible(bool value, bool previous)
    {
        visible = value; // maybe use parent setVisible(...)? would be better but which one?

M module-gui/gui/widgets/BoxLayout.hpp => module-gui/gui/widgets/BoxLayout.hpp +0 -1
@@ 97,7 97,6 @@ namespace gui
        bool removeWidget(Item *item) override;
        bool erase(Item *item) override;
        void erase() override;
        std::list<DrawCommand *> buildDrawList() override;
        /// add item if it will fit in box, return true on success
        /// axis sets direction to define space left in container
        template <Axis axis> void addWidget(Item *item);

M module-gui/gui/widgets/CMakeLists.txt => module-gui/gui/widgets/CMakeLists.txt +0 -1
@@ 21,7 21,6 @@ target_sources( ${PROJECT_NAME}
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayout.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/BoxLayoutSizeStore.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/PageLayout.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Layout.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/TopBar/SIM.cpp"
        "${CMAKE_CURRENT_LIST_DIR}/Text.cpp"

M module-gui/gui/widgets/CheckBox.hpp => module-gui/gui/widgets/CheckBox.hpp +0 -1
@@ 26,7 26,6 @@ namespace gui
                 std::function<void(const UTF8 &text)> bottomBarTemporaryMode = nullptr,
                 std::function<void()> bottomBarRestoreFromTemporaryMode      = nullptr,
                 bool textOnLeft                                              = true);
        virtual ~CheckBox() override = default;

        void setImageVisible(bool state);
        bool isChecked();

M module-gui/gui/widgets/Circle.cpp => module-gui/gui/widgets/Circle.cpp +3 -12
@@ 75,24 75,15 @@ namespace gui
          isFilled{_filled}, fillColor{_fillColor}, focusBorderColor{_focusBorderColor}
    {}

    std::list<DrawCommand *> Circle::buildDrawList()
    void Circle::buildDrawListImplementation(std::list<Command> &commands)
    {
        if (!visible) {
            return {};
        }

        auto circle = new CommandCircle(
        auto circle = std::make_unique<CommandCircle>(
            center, radius, focus ? focusPenWidth : penWidth, focus ? focusBorderColor : color, isFilled, fillColor);
        circle->areaX = widgetArea.x;
        circle->areaY = widgetArea.y;
        circle->areaW = widgetArea.w;
        circle->areaH = widgetArea.h;

        std::list<DrawCommand *> commands;
        commands.push_back(circle);

        auto childrenCommands = Item::buildChildrenDrawList();
        commands.splice(commands.end(), childrenCommands);
        return commands;
        commands.emplace_back(std::move(circle));
    }
} // namespace gui

M module-gui/gui/widgets/Circle.hpp => module-gui/gui/widgets/Circle.hpp +1 -2
@@ 5,7 5,6 @@

#include <list>
#include <cstdint>

#include "Arc.hpp"
#include "Common.hpp"
#include "Style.hpp"


@@ 41,7 40,7 @@ namespace gui

        Circle(Item *parent, const Circle::ShapeParams &params);

        std::list<DrawCommand *> buildDrawList() override;
        void buildDrawListImplementation(std::list<Command> &commands) override;

      private:
        Circle(Item *parent,

M module-gui/gui/widgets/GridLayout.hpp => module-gui/gui/widgets/GridLayout.hpp +0 -1
@@ 26,7 26,6 @@ namespace gui
        {}
        GridLayout() : GridLayout(0, 0, 0, 0, {0, 0})
        {}
        ~GridLayout() override = default;
        /// when reached top -> start from bottom. When reached left, start from right.
        bool navigationRotate = true;
        void resizeItems() override;

M module-gui/gui/widgets/Image.cpp => module-gui/gui/widgets/Image.cpp +3 -20
@@ 50,29 50,14 @@ namespace gui
        }
    }

    std::list<DrawCommand *> Image::buildDrawList()
    void Image::buildDrawListImplementation(std::list<Command> &commands)
    {

        std::list<DrawCommand *> commands;

        // check if widget is visible
        if (visible == false)
            return commands;

        // get children draw commands
        std::list<DrawCommand *> childrenCommands = Item::buildDrawList();
        if (!childrenCommands.empty())
            commands.merge(childrenCommands);

        // set local draw commands
        CommandImage *img = new CommandImage{};

        auto img = std::make_unique<CommandImage>();
        // image
        img->x = drawArea.x;
        img->y = drawArea.y;
        img->w = drawArea.w;
        img->h = drawArea.h;

        // cmd part
        img->areaX = img->x;
        img->areaY = img->y;


@@ 81,9 66,7 @@ namespace gui

        img->imageID = this->imageMap->getID();

        commands.push_back(img);

        return commands;
        commands.emplace_back(std::move(img));
    }

} /* namespace gui */

M module-gui/gui/widgets/Image.hpp => module-gui/gui/widgets/Image.hpp +2 -5
@@ 29,14 29,11 @@ namespace gui
        Image(Item *parent, uint32_t x, uint32_t y, const UTF8 imgName = UTF8{""})
            : Image(parent, x, y, 0u, 0u, imgName)
        {}
        virtual ~Image() = default;
        /// set image with id

        bool set(int id);
        /// set image with string name
        void set(const UTF8 &name);

        // virtual methods from Item
        std::list<DrawCommand *> buildDrawList();
        void buildDrawListImplementation(std::list<Command> &commands) override;
    };

} /* namespace gui */

M module-gui/gui/widgets/Item.cpp => module-gui/gui/widgets/Item.cpp +16 -10
@@ 10,11 10,7 @@
#include <algorithm> // for find
#include <list>      // for list<>::iterator, list, operator!=, _List...
#include <memory>

namespace gui
{
    class DrawCommand;
}
#include <DrawCommand.hpp>

namespace gui
{


@@ 107,21 103,31 @@ namespace gui
        visible = value;
    }

    std::list<DrawCommand *> Item::buildDrawList()
    std::list<Command> Item::buildDrawList()
    {
        return buildChildrenDrawList();
        if (not visible) {
            return {};
        }
        auto commands = std::list<Command>();
        if (preBuildDrawListHook != nullptr) {
            preBuildDrawListHook(commands);
        }
        buildDrawListImplementation(commands);
        buildChildrenDrawList(commands);
        if (postBuildDrawListHook != nullptr) {
            postBuildDrawListHook(commands);
        }
        return commands;
    }

    std::list<DrawCommand *> Item::buildChildrenDrawList()
    void Item::buildChildrenDrawList(std::list<Command> &commands)
    {
        std::list<DrawCommand *> commands;
        for (auto widget : children) {
            auto drawCommands = widget->buildDrawList();
            if (!drawCommands.empty()) {
                commands.splice(commands.end(), drawCommands);
            }
        }
        return commands;
    }

    void Item::setArea(BoundingBox area)

M module-gui/gui/widgets/Item.hpp => module-gui/gui/widgets/Item.hpp +13 -9
@@ 14,10 14,8 @@
#include <list>                 // for list
#include <memory>               // for unique_ptr
#include <utility>              // for move
namespace gui
{
    class DrawCommand;
}
#include <core/DrawCommandForward.hpp>

namespace gui
{
    class InputEvent;


@@ 277,11 275,17 @@ namespace gui
        /// calls onDimensionChanged & updateDrwArea
        /// @attention should be bind to area
        virtual void setBoundingBox(const BoundingBox &new_box);
        /// list of commands for renderer to draw elements on screen
        /// all elements consist od lines, arcs, rectangles, text and images
        /// for full list of elements please see renderer code
        /// entry function to create commands to execute in renderer to draw on screen
        /// @note we should consider lazy evaluation prior to drawing on screen, rather than on each resize of elements
        virtual std::list<DrawCommand *> buildDrawList();
        /// @return list of commands for renderer to draw elements on screen
        virtual std::list<Command> buildDrawList() final;
        /// Implementation of DrawList per Item to be drawn on screen
        /// This is called from buildDrawList before children elements are added
        /// should be = 0;
        virtual void buildDrawListImplementation(std::list<Command> &commands)
        {}
        std::function<void(std::list<Command> &)> preBuildDrawListHook  = nullptr;
        std::function<void(std::list<Command> &)> postBuildDrawListHook = nullptr;
        /// sets radius of Item box
        /// @note this should be moved to Rect
        virtual void setRadius(int value);


@@ 350,7 354,7 @@ namespace gui
        /// On change of position or size this method will recalculate visible part of the widget
        /// considering widgets hierarchy and calculate absolute position of drawing primitives.
        virtual void updateDrawArea();
        std::list<DrawCommand *> buildChildrenDrawList();
        virtual void buildChildrenDrawList(std::list<Command> &commands) final;
        /// Pointer to navigation object. It is added when object is set for one of the directions
        gui::Navigation *navigationDirections = nullptr;
    };

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

///*
// * KeyEvent.hpp
// *
// *  Created on: 25 kwi 2019
// *      Author: robert
// */
//
//#ifndef GUI_WIDGETS_KEYEVENT_HPP_
//#define GUI_WIDGETS_KEYEVENT_HPP_
//
//#include <cstdint>
//
// namespace gui {
//
// enum class KeyCode {
//	KEY_LEFT,
//	KEY_UP,
//	KEY_RIGHT,
//	KEY_DOWN,
//	KEY_LF,
//	KEY_RF,
//	KEY_ENTER,
//	KEY_0,
//	KEY_1,
//	KEY_2,
//	KEY_3,
//	KEY_4,
//	KEY_5,
//	KEY_6,
//	KEY_7,
//	KEY_8,
//	KEY_9,
//	KEY_AST,
//	KEY_PND,
//	KEY_GREEN,
//	KEY_RED,
//	KEY_VOLUP,
//	KEY_VOLDN,
//	KEY_TORCH,
//	SWITCH_UP,
//	SWITCH_MID,
//	SWITCH_DN
//};
//
// enum class KeyState {
//	KEY_UNKNOWN         = 0x00,
//	KEY_PRESSED         = 0x01,
//    KEY_RELEASED_SHORT  = 0x02,
//    KEY_RELEASED_LONG   = 0x04,
//	KEY_CYCLE           = 0x08
//};
//
// class KeyEvent {
// public:
//	//defines mapped code of the pressed button
//	KeyCode keyCode;
//	//defines state of the button
//	KeyState keyState;
//	//defines how long button was pressed
//	uint32_t duration;
//
//	KeyEvent();
//	virtual ~KeyEvent();
//};
//
//} /* namespace gui */
//
//#endif /* GUI_WIDGETS_KEYEVENT_HPP_ */

M module-gui/gui/widgets/Label.cpp => module-gui/gui/widgets/Label.cpp +23 -44
@@ 215,53 215,32 @@ namespace gui
        calculateDisplayText();
    }

    std::list<DrawCommand *> Label::buildDrawList()
    void Label::buildDrawListImplementation(std::list<Command> &commands)
    {

        std::list<DrawCommand *> commands;

        // check if widget is visible
        if (visible == false) {
            return commands;
        }

        // get children draw commands
        std::list<DrawCommand *> commandsChildren;
        commandsChildren = Item::buildDrawList();

        // base class draw commands
        std::list<DrawCommand *> commandsBase;
        commandsBase = gui::Rect::buildDrawList();

        commands.splice(commands.end(), commandsBase);
        // set local draw commands - text command
        if (font != nullptr) {
            CommandText *textCmd = new CommandText();
            textCmd->str         = textDisplayed;
            textCmd->fontID      = font->id;
            textCmd->color       = textColor;

            textCmd->x          = drawArea.x;
            textCmd->y          = drawArea.y;
            textCmd->w          = drawArea.w;
            textCmd->h          = drawArea.h;
            textCmd->tx         = textArea.x;
            textCmd->ty         = textArea.y;
            textCmd->tw         = textArea.w;
            textCmd->th         = textArea.h;
            textCmd->charsWidth = stringPixelWidth;

            textCmd->areaX = widgetArea.x;
            textCmd->areaY = widgetArea.y;
            textCmd->areaW = widgetArea.w;
            textCmd->areaH = widgetArea.h;
            commands.push_back(textCmd);
            auto cmd    = std::make_unique<CommandText>();
            cmd->str    = textDisplayed;
            cmd->fontID = font->id;
            cmd->color  = textColor;

            cmd->x          = drawArea.x;
            cmd->y          = drawArea.y;
            cmd->w          = drawArea.w;
            cmd->h          = drawArea.h;
            cmd->tx         = textArea.x;
            cmd->ty         = textArea.y;
            cmd->tw         = textArea.w;
            cmd->th         = textArea.h;
            cmd->charsWidth = stringPixelWidth;

            cmd->areaX = widgetArea.x;
            cmd->areaY = widgetArea.y;
            cmd->areaW = widgetArea.w;
            cmd->areaH = widgetArea.h;

            commands.emplace_back(std::move(cmd));
        }
        if (not commandsChildren.empty()) {
            commands.splice(commands.end(), commandsChildren);
        }

        return commands;
        Rect::buildDrawListImplementation(commands);
    }

    bool Label::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)

M module-gui/gui/widgets/Label.hpp => module-gui/gui/widgets/Label.hpp +1 -1
@@ 125,7 125,7 @@ namespace gui
        void setFont(RawFont *font);
        RawFont *getFont() const noexcept;
        // virtual methods
        std::list<DrawCommand *> buildDrawList() override;
        void buildDrawListImplementation(std::list<Command> &commands) override;
        uint32_t getTextNeedSpace() const noexcept;
        /// line: height
        uint32_t getTextHeight() const noexcept;

D module-gui/gui/widgets/Layout.cpp => module-gui/gui/widgets/Layout.cpp +0 -0
M module-gui/gui/widgets/ListView.cpp => module-gui/gui/widgets/ListView.cpp +0 -10
@@ 357,16 357,6 @@ namespace gui
        }
    };

    std::list<DrawCommand *> ListView::buildDrawList()
    {
        // check if widget is visible
        if (visible == false) {
            return std::list<DrawCommand *>();
        }

        return gui::Rect::buildDrawList();
    }

    bool ListView::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)
    {
        Rect::onDimensionChanged(oldDim, newDim);

M module-gui/gui/widgets/ListView.hpp => module-gui/gui/widgets/ListView.hpp +0 -1
@@ 78,7 78,6 @@ namespace gui
        void onProviderDataUpdate();

        // virtual methods from Item
        std::list<DrawCommand *> buildDrawList() override;
        bool onInput(const InputEvent &inputEvent) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
        auto handleRequestResize(const Item *, unsigned short request_w, unsigned short request_h) -> Size override;

M module-gui/gui/widgets/ProgressBar.cpp => module-gui/gui/widgets/ProgressBar.cpp +6 -21
@@ 47,24 47,12 @@ namespace gui
        setValue(absoluteValue);
    }

    std::list<DrawCommand *> ProgressBar::buildDrawList()
    void ProgressBar::buildDrawListImplementation(std::list<Command> &commands)
    {
        if (!visible) {
            return {};
        }

        std::list<DrawCommand *> baseCommands = gui::Rect::buildDrawList();
        auto it                               = baseCommands.begin();
        it++;
        CommandRectangle *fill = static_cast<CommandRectangle *>(*it);

        uint32_t progressSize = maxValue == 0U ? 0 : (currentValue * widgetArea.w) / maxValue;
        fill->w               = progressSize;
        drawArea.w            = progressSize;

        std::list<DrawCommand *> commands;
        commands.splice(commands.end(), baseCommands, it);
        commands.splice(commands.end(), baseCommands);
        return commands;
        gui::Rect::buildDrawListImplementation(commands);
    }

    bool ProgressBar::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)


@@ 137,17 125,14 @@ namespace gui
        return static_cast<float>(currentValue) / maxValue;
    }

    std::list<DrawCommand *> CircularProgressBar::buildDrawList()
    void CircularProgressBar::buildDrawListImplementation(std::list<Command> &commands)
    {
        using namespace trigonometry;

        if (!visible) {
            return {};
        }

        progressArc->setSweepAngle(getPercentageValue() * FullAngle);
        progressIndicator->setCenter(calculateProgressIndicatorCenter());
        return Circle::buildDrawList();

        Circle::buildDrawListImplementation(commands);
    }

    bool CircularProgressBar::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim)

M module-gui/gui/widgets/ProgressBar.hpp => module-gui/gui/widgets/ProgressBar.hpp +2 -2
@@ 30,7 30,7 @@ namespace gui
        void setValue(unsigned int value) noexcept override;
        void setPercentageValue(unsigned int value) noexcept override;

        std::list<DrawCommand *> buildDrawList() override;
        void buildDrawListImplementation(std::list<Command> &commands) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;

      private:


@@ 50,7 50,7 @@ namespace gui
        void setValue(unsigned int value) noexcept override;
        void setPercentageValue(unsigned int value) noexcept override;

        auto buildDrawList() -> std::list<DrawCommand *> override;
        void buildDrawListImplementation(std::list<Command> &commands) override;
        auto onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) -> bool override;

      private:

M module-gui/gui/widgets/Rect.cpp => module-gui/gui/widgets/Rect.cpp +7 -22
@@ 93,21 93,9 @@ namespace gui
        yapSize = value;
    }

    std::list<DrawCommand *> Rect::buildDrawList()
    void Rect::buildDrawListImplementation(std::list<Command> &commands)
    {

        std::list<DrawCommand *> commands;

        // check if widget is visible
        if (visible == false) {
            return commands;
        }

        // get children draw commands
        std::list<DrawCommand *> childrenCommands = Item::buildDrawList();

        // set local draw commands
        CommandRectangle *rect = new CommandRectangle();
        auto rect = std::make_unique<CommandRectangle>();

        rect->x         = drawArea.x;
        rect->y         = drawArea.y;


@@ 123,21 111,18 @@ namespace gui
        rect->yaps      = yaps;
        rect->yapSize   = yapSize;
        rect->radius    = radius;
        if (focus)
        if (focus) {
            rect->penWidth = penFocusWidth;
        else
        }
        else {
            rect->penWidth = penWidth;
        }

        rect->filled      = filled;
        rect->borderColor = borderColor;
        rect->fillColor   = fillColor;

        commands.push_back(rect);

        if (!childrenCommands.empty())
            commands.insert(commands.end(), childrenCommands.begin(), childrenCommands.end());

        return commands;
        commands.emplace_back(std::move(rect));
    }

} /* namespace gui */

M module-gui/gui/widgets/Rect.hpp => module-gui/gui/widgets/Rect.hpp +1 -1
@@ 50,7 50,7 @@ namespace gui
        virtual void setYaps(RectangleYap yaps);
        virtual void setYapSize(unsigned short value);
        void setFilled(bool val);
        std::list<DrawCommand *> buildDrawList() override;
        void buildDrawListImplementation(std::list<Command> &commands) override;
    };

} /* namespace gui */

M module-gui/gui/widgets/RichTextParser.cpp => module-gui/gui/widgets/RichTextParser.cpp +4 -2
@@ 15,9 15,11 @@
#include <module-utils/pugixml/src/pugixml.hpp>
#include <utility>

#ifndef DEBUG_RTP
#ifdef DEBUG_RTP
const std::string node_types[] = {"null", "document", "element", "pcdata ", "cdata", "comment", "pi", "declaration"};
#define log_parser(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_parser(...)
#endif

namespace text


@@ 426,7 428,7 @@ namespace gui::text

    auto RichTextParser::parse(const UTF8 &text, TextFormat *base_style) -> std::unique_ptr<TextDocument>
    {
        LOG_DEBUG("parsing: %s", text.c_str());
        log_parser("parsing: %s", text.c_str());
        if (text.empty() || base_style == nullptr) {
            LOG_ERROR("no: %s", text.empty() ? "text" : "base style");
            return std::unique_ptr<TextDocument>();

M module-gui/gui/widgets/Span.hpp => module-gui/gui/widgets/Span.hpp +1 -1
@@ 21,7 21,7 @@ namespace gui

        Span(Item *parent, Axis axis, unsigned int size) : Span(axis, size)
        {
            if (parent) {
            if (parent != nullptr) {
                parent->addWidget(this);
            }
        }

M module-gui/gui/widgets/Text.cpp => module-gui/gui/widgets/Text.cpp +4 -2
@@ 24,6 24,7 @@
#include <RawFont.hpp>
#include <RichTextParser.hpp>
#include "Lines.hpp"
#include <DrawCommand.hpp>

#if DEBUG_GUI_TEXT == 1
#define debug_text(...) LOG_DEBUG(__VA_ARGS__)


@@ 70,6 71,8 @@ namespace gui

        setBorderColor(gui::ColorFullBlack);
        setEdges(RectangleEdge::All);

        preBuildDrawListHook = [this](std::list<Command> &commands) { preBuildDrawListHookImplementation(commands); };
    }

    Text::Text() : Text(nullptr, 0, 0, 0, 0)


@@ 434,7 437,7 @@ namespace gui
        }
    }

    std::list<DrawCommand *> Text::buildDrawList()
    void Text::preBuildDrawListHookImplementation(std::list<Command> &commands)
    {
        // we can't build elements to show just before showing.
        // why? because we need to know if these elements fit in


@@ 452,7 455,6 @@ namespace gui
                       return str.c_str();
                   }()
                                .c_str());
        return Rect::buildDrawList();
    }

    void Text::buildDocument(const UTF8 &text)

M module-gui/gui/widgets/Text.hpp => module-gui/gui/widgets/Text.hpp +1 -1
@@ 78,7 78,7 @@ namespace gui
        auto handleNavigation(const InputEvent &inputEvent) -> bool;
        auto handleEnter() -> bool;

        auto buildDrawList() -> std::list<DrawCommand *> override;
        void preBuildDrawListHookImplementation(std::list<Command> &commands);
        /// redrawing lines
        /// it redraws visible lines on screen and if needed requests resize in parent
        virtual void drawLines();

M module-gui/gui/widgets/TopBar.cpp => module-gui/gui/widgets/TopBar.cpp +4 -20
@@ 25,16 25,6 @@ namespace gui
    gui::TopBar::TimeMode TopBar::timeMode = TimeMode::TIME_24H;
    uint32_t TopBar::time                  = 0;

    TopBar::TopBar()
    {

        prepareWidget();

        setFillColor(ColorFullWhite);
        setBorderColor(ColorNoColor);
        setFilled(true);
        setSize(480, 50);
    }
    TopBar::TopBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h) : Rect{parent, x, y, w, h}
    {



@@ 45,9 35,11 @@ namespace gui
        setFilled(true);
        setSize(480, 50);
        updateDrawArea();

        preBuildDrawListHook = [this](std::list<Command> &) {
            setTime(time, (timeMode == TimeMode::TIME_24H) ? true : false);
        };
    }
    TopBar::~TopBar()
    {}

    void TopBar::batteryShowBars(uint32_t val)
    {


@@ 285,14 277,6 @@ namespace gui
        return timeLabel->getText();
    }

    std::list<DrawCommand *> TopBar::buildDrawList()
    {

        // make sure that time text is updated.
        setTime(time, (timeMode == TimeMode::TIME_24H) ? true : false);

        return Rect::buildDrawList();
    }

    void TopBar::simSet()
    {

M module-gui/gui/widgets/TopBar.hpp => module-gui/gui/widgets/TopBar.hpp +0 -10
@@ 76,14 76,7 @@ namespace gui
        } elements = {false, false, false, false, true, true};

      public:
        TopBar();
        TopBar(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
        virtual ~TopBar();

        /**
         * @brief Sets mode of time displaying according to TimeMode enum
         * @note Variable is common for all instances of TopBar
         */

        /**
         * @brief Hides or shows images.


@@ 115,9 108,6 @@ namespace gui
        {
            return time;
        };

        // virtual methods from Item
        std::list<DrawCommand *> buildDrawList() override;
    };

} /* namespace gui */

M module-gui/gui/widgets/Window.cpp => module-gui/gui/widgets/Window.cpp +6 -18
@@ 17,7 17,7 @@

namespace gui
{
    Window::Window(std::string name) : Item(), refreshMode{RefreshModes::GUI_REFRESH_FAST}, name{name}
    Window::Window(std::string name) : Item(), name{name}
    {}

    void Window::onBeforeShow(ShowMode mode, SwitchData *data)


@@ 26,36 26,24 @@ namespace gui
    void Window::onClose()
    {}

    void Window::getRefreshArea(RefreshModes &mode, uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h)
    void Window::getRefreshArea(uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h)
    {
        x    = widgetArea.x;
        y    = widgetArea.y;
        w    = widgetArea.w;
        h    = widgetArea.h;
        mode = refreshMode;
    }

    bool Window::handleSwitchData(SwitchData *data)
    {
        return true;
        return false;
    }

    std::list<DrawCommand *> Window::buildDrawList()
    void Window::buildDrawListImplementation(std::list<Command> &commands)
    {

        std::list<DrawCommand *> commands;
        std::list<DrawCommand *> childrenCommands = Item::buildDrawList();

        DrawCommand *clearCommand = new DrawCommand();
        auto clearCommand         = std::make_unique<DrawCommand>();
        clearCommand->id          = DrawCommandID::GUI_DRAW_CLEAR;

        commands.push_back(clearCommand);

        if (!childrenCommands.empty()) {
            commands.splice(commands.end(), childrenCommands);
        }

        return commands;
        commands.emplace_back(std::move(clearCommand));
    }

    bool Window::onInput(const InputEvent &inputEvent)

M module-gui/gui/widgets/Window.hpp => module-gui/gui/widgets/Window.hpp +4 -3
@@ 30,7 30,6 @@ namespace gui
    class Window : public Item
    {
      protected:
        RefreshModes refreshMode;
        /// name of window used for windows switching
        std::string name;



@@ 43,7 42,7 @@ namespace gui
        /// @note this is most likely being duplicated by handleSwitchData
        virtual void onBeforeShow(ShowMode mode, SwitchData *data);
        virtual void onClose();
        virtual void getRefreshArea(RefreshModes &mode, uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h);
        virtual void getRefreshArea(uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h);

        /// run prior to onBeforeShow
        /// @note this is most likely duplicate of onBeforeShow


@@ 58,7 57,9 @@ namespace gui

        // virtual methods from Item
        bool onInput(const InputEvent &inputEvent) override;
        std::list<DrawCommand *> buildDrawList() override;

        void buildDrawListImplementation(std::list<Command> &commands) override;

        std::string getName()
        {
            return name;

M module-gui/test/test-catch/test-gui.cpp => module-gui/test/test-catch/test-gui.cpp +1 -7
@@ 97,15 97,9 @@ TEST_CASE("Draw window with labels")

    // vector with draw commands
    // context for drawing commands
    std::list<gui::DrawCommand *> commandsList = win->buildDrawList();
    std::vector<gui::DrawCommand *> commands{commandsList.begin(), commandsList.end()};
    auto commandsList = win->buildDrawList();

    delete win;

    // cleanup
    for (auto cmd : commands) {
        delete cmd;
    }
}

TEST_CASE("Draw window with box layouts")

M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +4 -6
@@ 118,13 118,13 @@ namespace sgui
                // if suspend flag is set ignore any new message
                if (!suspendInProgress) {

                    if (dmsg->command == sgui::DrawMessage::DrawCommand::SHUTDOWN) {
                    if (dmsg->type == sgui::DrawMessage::Type::SHUTDOWN) {
                        LOG_WARN("Shutdown - received shutdown draw commands");
                        shutdownInProgress = true;
                    }

                    // if message carries suspend flag set flag in service and proceed
                    if (dmsg->command == sgui::DrawMessage::DrawCommand::SUSPEND) {
                    if (dmsg->type == sgui::DrawMessage::Type::SUSPEND) {
                        LOG_WARN("Suspended - received suspend draw commands");
                        suspendInProgress = true;
                    }


@@ 134,13 134,11 @@ namespace sgui
                        mode = dmsg->mode;
                    }

                    //				LOG_INFO("[ServiceGUI] Received %d draw commands", dmsg->commands.size());
                    // LOG_DEBUG("Received %d draw commands", dmsg->commands.size());

                    // lock access to commands vector, clear it and then copy commands from message to vector
                    if (xSemaphoreTake(semCommands, pdMS_TO_TICKS(1000)) == pdTRUE) {
                        commands.clear();
                        for (auto it = dmsg->commands.begin(); it != dmsg->commands.end(); it++)
                            commands.push_back(std::move(*it));
                        commands = std::move(dmsg->commands);
                        xSemaphoreGive(semCommands);
                    }
                    else {

M module-services/service-gui/ServiceGUI.hpp => module-services/service-gui/ServiceGUI.hpp +1 -1
@@ 58,7 58,7 @@ namespace sgui
        volatile bool rendering   = false;
        // set of commands recently received. If this vector is not empty and new set of commands is received
        // previous commands are removed.
        std::vector<std::unique_ptr<gui::DrawCommand>> commands;
        std::list<std::unique_ptr<gui::DrawCommand>> commands;
        //	uint32_t timer_id= 0;
        gui::RefreshModes mode = gui::RefreshModes::GUI_REFRESH_DEEP;


M module-services/service-gui/WorkerGUI.cpp => module-services/service-gui/WorkerGUI.cpp +3 -11
@@ 40,29 40,21 @@ namespace sgui
            xQueueReceive(queue, &received, 0);

            // take all unique pointers
            std::vector<std::unique_ptr<gui::DrawCommand>> uniqueCommands;
            std::list<std::unique_ptr<gui::DrawCommand>> uniqueCommands;

            if (xSemaphoreTake(serviceGUI->semCommands, pdMS_TO_TICKS(1000)) == pdTRUE) {
                for (auto it = serviceGUI->commands.begin(); it != serviceGUI->commands.end(); it++)
                    uniqueCommands.push_back(std::move(*it));
                serviceGUI->commands.clear();
                uniqueCommands = std::move(serviceGUI->commands);
                xSemaphoreGive(serviceGUI->semCommands);
            }
            else {
                LOG_ERROR("Failed to acquire semaphore");
            }

            // create temporary vector of pointers to draw commands to avoid polluting renderer with smart pointers.
            std::vector<gui::DrawCommand *> commands;
            for (auto it = uniqueCommands.begin(); it != uniqueCommands.end(); it++)
                commands.push_back((*it).get());

            //		uint32_t start_tick = xTaskGetTickCount();
            serviceGUI->renderer.render(serviceGUI->renderContext, commands);
            serviceGUI->renderer.render(serviceGUI->renderContext, uniqueCommands);
            //		uint32_t end_tick = xTaskGetTickCount();
            //		LOG_INFO("[WorkerGUI] RenderingTime: %d", end_tick - start_tick);

            //			delete received;

            // notify gui service that rendering is complete
            auto message = std::make_shared<sys::DataMessage>(MessageType::GUIRenderingFinished);

M module-services/service-gui/messages/DrawMessage.cpp => module-services/service-gui/messages/DrawMessage.cpp +2 -15
@@ 2,28 2,15 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "DrawMessage.hpp"

#include "GUIMessage.hpp"

#include <Common.hpp>
#include <DrawCommand.hpp>
#include <MessageType.hpp>

namespace sgui
{

    DrawMessage::DrawMessage(const std::list<gui::DrawCommand *> &commandsList, gui::RefreshModes mode, DrawCommand cmd)
        : GUIMessage(MessageType::GUICommands), command{cmd}
    DrawMessage::DrawMessage(std::list<gui::Command> commands, gui::RefreshModes mode)
        : GUIMessage(MessageType::GUICommands), mode(mode), commands(std::move(commands))
    {

        this->mode = mode;
        for (auto cmd : commandsList) {
            if (cmd)
                commands.push_back(std::unique_ptr<gui::DrawCommand>(cmd));
        }
    }

    DrawMessage::~DrawMessage()
    {}

} /* namespace sgui */

M module-services/service-gui/messages/DrawMessage.hpp => module-services/service-gui/messages/DrawMessage.hpp +13 -19
@@ 4,7 4,6 @@
#pragma once

#include "GUIMessage.hpp"

#include <core/DrawCommand.hpp>
#include <gui/Common.hpp>
#include <Service/Message.hpp>


@@ 12,21 11,18 @@
#include <list>
#include <memory>

namespace gui
{
    class DrawCommand;
} // namespace gui
#include "Service/Message.hpp"
#include "core/DrawCommandForward.hpp"
#include "GUIMessage.hpp"
#include "gui/Common.hpp"

namespace sgui
{

    /*
     *
     */
    class DrawMessage : public GUIMessage
    {
      public:
        enum class DrawCommand
        enum class Type
        {
            NORMAL,
            SUSPEND,


@@ 35,17 31,15 @@ namespace sgui

      public:
        gui::RefreshModes mode;
        std::list<std::unique_ptr<gui::DrawCommand>> commands;
        std::list<gui::Command> commands;
        Type type = Type::NORMAL;

        /**
         * flag that informs that this is last rendering before suspending system.
         */
        DrawCommand command = DrawCommand::NORMAL;
        DrawMessage(std::list<gui::Command> commandsList, gui::RefreshModes mode);

        DrawMessage(const std::list<gui::DrawCommand *> &commandsList,
                    gui::RefreshModes mode,
                    DrawCommand cmd = DrawCommand::NORMAL);
        virtual ~DrawMessage();
        void setCommandType(Type type)
        {
            this->type = type;
        }
    };

} /* namespace sgui */
} // namespace sgui

M source/MessageType.hpp => source/MessageType.hpp +2 -1
@@ 147,7 147,8 @@ enum class MessageType
    // keyboard messages
    KBDKeyEvent,

    AppSwitch, ///< application receives this message from application manager. It a signal to gain or loose focus.
    AppMessage, //< generic application message
    AppSwitch,  ///< application receives this message from application manager. It a signal to gain or loose focus.
    AppSwitchWindow, ///< This is internal message transmitted within application to change window. Additional command
                     ///< and data are transmitted with it.
    AppInputEvent,   ///< used after key event translation to send input event to application