~aleteoryx/muditaos

b996cff40c6b0b34dfd72ab1a5bf14561963005b — Tomasz Langowski 5 years ago fe4b425
[EGD-5176] Documentation update for gui item and gridlayout

Documentation update for gui item and gridlayout
2 files changed, 156 insertions(+), 79 deletions(-)

M module-gui/gui/widgets/GridLayout.hpp
M module-gui/gui/widgets/Item.hpp
M module-gui/gui/widgets/GridLayout.hpp => module-gui/gui/widgets/GridLayout.hpp +39 -15
@@ 7,11 7,11 @@

namespace gui
{

    /// GridLayout lays out items (widgets) in a grid.
    class GridLayout : public BoxLayout
    {
      protected:
        /// size of singular grid element
        /// Data container for size of singular grid element
        struct GridSize
        {
            uint32_t x = 0;


@@ 19,35 19,59 @@ namespace gui
        } grid;

      public:
        GridLayout(Item *parent,
                   const uint32_t &x,
                   const uint32_t &y,
                   const uint32_t &width,
                   const uint32_t &height,
                   GridSize cellSize);
        GridLayout(
            Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h, GridSize grid);
        GridLayout(const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h, GridSize grid)
            : GridLayout(nullptr, x, y, w, h, grid)
            const uint32_t &x, const uint32_t &y, const uint32_t &width, const uint32_t &height, GridSize cellSize)
            : GridLayout(nullptr, x, y, width, height, cellSize)
        {}
        GridLayout() : GridLayout(0, 0, 0, 0, {0, 0})
        {}
        /// Calculates Items position.
        ///@note It is called when new widgets are added to layout or on resize requests.
        ///@attention Function does not yet resize items -> only items position are calculated"
        void resizeItems() override;
        /// Sets navigation for layout children (for widgets/items inside layout).
        ///@note It is called when new widgets are added to layout or on resize requests.
        void setNavigation() override;

        /// calculated rows count in grid layout.
        uint32_t rowSize = 0;
        /// calculated columns count in grid layout.
        uint32_t colSize = 0;

      private:
        /// function to handle items that do not fit into grid layout area
        /// @param maxItemsInArea : maximum amount of items that fits into grid size
        void handleItemsOutOfGridLayoutArea(uint32_t maxItemsInArea);
        Item *getFirstActiveItem(uint32_t startposition, int step);
        /// retrieves active item from children items with defined step to next item
        /// in case when item in startPosition is not active
        /// @param startPosition : starting point for calculation
        /// @param step : single step used to search for next item
        /// @return pointer to active Item or nullptr in case when active Item has not been found
        Item *getFirstActiveItem(uint32_t startPosition, int step);
        /// retrieves index of last item in the selected column.
        ///@param col : column index for which calculation shall be made
        ///@return calculated last item index for selected column index
        inline uint32_t getLastColumnIndex(uint32_t col)
        {
            auto lastcolumnindex = col;
            while ((lastcolumnindex + colSize) < children.size())
                lastcolumnindex += colSize;
            return lastcolumnindex;
            auto lastColumnIndex = col;
            while ((lastColumnIndex + colSize) < children.size())
                lastColumnIndex += colSize;
            return lastColumnIndex;
        }
        /// retrieves index of last item in the selected row.
        ///@param row : row index for which calculation shall be made
        ///@return calculated last item index for selected row index
        inline uint32_t getLastRowIndex(uint32_t row)
        {
            uint32_t lastrowindex = colSize * row + (colSize - 1);
            while (lastrowindex >= children.size())
                lastrowindex--;
            return lastrowindex;
            uint32_t lastRowIndex = colSize * row + (colSize - 1);
            while (lastRowIndex >= children.size())
                lastRowIndex--;
            return lastRowIndex;
        }
    };


M module-gui/gui/widgets/Item.hpp => module-gui/gui/widgets/Item.hpp +117 -64
@@ 32,6 32,7 @@ namespace gui

namespace gui
{
    /// enumaration that contains gui item types
    enum class ItemType
    {
        ITEM = 0,


@@ 46,25 47,24 @@ namespace gui
        VBOX,
        HBOX
    };

    /// Base class for all GUI items.
    /// @details It is a basic element for creating widgets and applications
    /// that make up the GUI (Graphic User Interface) in MuditaOS
    class Item
    {
      private:
        /// list of timers so that item could have it's timers in itself
        std::list<std::unique_ptr<Timer>> timers;

      public:
        // flag that informs whether item has a focus
        /// flag that informs whether item has a focus
        bool focus;
        /// pointer to the child item that has focus
        Item *focusItem = nullptr;
        /// item type of the widget - could be used to check what type item we are working on
        /// right now unused except Text, where it calles callback for gui::BoxLayout which does nothing
        /// right now unused except Text, where it calls callback for gui::BoxLayout which does nothing
        ItemType type = ItemType::ITEM;
        // pointer to the parent Item
        /// pointer to the parent Item
        Item *parent = nullptr;
        // list of items that have the same parent.
        /// list of item's children. @note Items can have only one parent.
        std::list<Item *> children;
        /// enumaration with options for item bounding box (size & position) area
        enum class Area
        {
            Min,


@@ 72,15 72,16 @@ namespace gui
            Draw,
            Max,
        };
        /// actual bounding box of the item. This is in coordinates of the parent widget.
        /// actual bounding box (size & position) of the item. This is in coordinates of the parent widget.
        BoundingBox widgetArea;
        /// bounding box of the item minimum size,
        /// bounding box (size & position) of the item minimum size,
        BoundingBox widgetMinimumArea;
        /// bounding box of the item maximal size,
        /// bounding box (size & position) of the item maximal size,
        BoundingBox widgetMaximumArea;
        // bounding box used for drawing. This is in coordinates of window
        /// bounding box (size & position) used for drawing. This is in coordinates of window
        BoundingBox drawArea; // drawableArea would be more accurate
                              // maximal bounding box size
        /// gets bounding box for selected area
        auto area(Area which = Area::Normal) -> BoundingBox &
        {
            switch (which) {


@@ 96,26 97,27 @@ namespace gui
                return widgetArea;
            }
        }

        Padding padding;
        Margins margins;

        Alignment alignment;

        /// radius of corner, default 0
        short radius = 0;
        /// flag that defines if item is active
        /// if false -> than it shouldn't be used with onInput, navigation etc.

        /// flag that defines if item is active.
        /// @details When flag is set to true item is focusable (focus on item can be set)
        /// and clickable (item action can be activated). Otherwise item is non focusable and non clickable.
        /// @note if false -> than it shouldn't be used with onInput, navigation etc.
        bool activeItem = true;
        /// flag that defines whether widget is visible (this is - should be rendered)
        bool visible;
        // policy for changing vertical size if Item is placed inside layout
        /// policy for changing vertical size if Item is placed inside layout.
        LayoutVerticalPolicy verticalPolicy;
        // policy for changing horizontal size if Item is placed inside layout
        /// policy for changing horizontal size if Item is placed inside layout.
        LayoutHorizontalPolicy horizontalPolicy;
        // Maximum height to which Layout base widget can scale current widget
        /// Maximum height to which Layout base widget can scale current widget.
        uint16_t maxHeight;
        // Maximum width to which Layout base widget can scale current widget
        /// Maximum width to which Layout base widget can scale current widget.
        uint16_t maxWidth;

        /// @defgroup callbacks     Item callback functions


@@ 128,23 130,27 @@ namespace gui
        /// @{

        /// called when item looses/gains focus
        /// @param `this` : item
        std::function<bool(Item &)> focusChangedCallback;
        /// called when item has dimensions changed
        /// @param `this` : item
        /// @param data : new bounding box area
        /// @note should be part of widgetArea
        std::function<bool(Item &, BoundingBox data)> dimensionChangedCallback;
        /// called when item is activated, this is enter is pressed
        /// @param `this` item
        /// @param `this` : item
        std::function<bool(Item &)> activatedCallback;
        /// callback when any key is pressed
        /// @param `this` item
        /// @param `InputEvent`
        /// @param `this` : item
        /// @param inputEvent : input event e.g. key pressed
        std::function<bool(Item &, const InputEvent &inputEvent)> inputCallback;
        /// callback when timer is called on Item and onTimer is executed
        /// @param `this` item
        /// @param `timer` which triggered this callback
        /// @param `this` : item
        /// @param `timer` : which triggered this callback
        std::function<bool(Item &, Timer &)> timerCallback = nullptr;

        /// callback on navigation, called when item passes navigation to handle by it's children
        /// callback on navigation, called when item passes navigation to handle by its children
        /// @param `InputEvent` : input event e.g. key pressed
        /// @attention when child handles navigation it should return true, so that parent won't perform action for that
        std::function<bool(const InputEvent &)> itemNavigation = nullptr;



@@ 152,76 158,97 @@ namespace gui

        ///  @defgroup focus    functions handling focus
        /// @{

        /// navigation handler for input events e.g. keyboard key pressed
        /// @param inputEvent : input event e.g. key pressed
        bool handleNavigation(const InputEvent inputEvent);
        /// sets/resets focus on `this` Item and runs focusChangedCallback for it
        /// sets/resets focus on this Item and runs focusChangedCallback for it
        /// @param state : true to set focus on item, false to clear focus from item
        bool setFocus(bool state);
        /// sets/resets child with focus in `this` Item
        /// runs focusChangedCallback on item which changes
        /// sets/resets focus on provided item child if one exists.
        /// @param item : this
        /// @note runs focusChangedCallback on item which changes
        /// @attention focusItem is just a pointer, might crash if item with focus was removed
        void setFocusItem(Item *item);
        /// gettter for focus item
        /// getter for focus item
        /// @attention focusItem is just a pointer, might crash if item with focus was removed
        Item *getFocusItem() const;

        /// @}

        /// @defgroup callbackCallers   functions which should call functors from callbacks group
        /// @{

        /// called from setFocus, does nothing (which means it doesn't call focusChangedCallback
        /// @param state : new focus state
        virtual bool onFocus(bool state);
        /// called when `this` Item was pressed with enter (middle key on phone action keys), used for callback input
        /// handling calls activatedCallback
        /// @param[in]: data unused
        /// called when this Item was pressed with enter (middle key on phone action keys),
        /// used for callback input handling calls activatedCallback
        /// @param[in] data : unused
        virtual bool onActivated(void *data);
        /// called when any key is pressed, before onActivated , after focus
        /// calls: inputCallback
        /// @param InputEvent : input event e.g. key pressed
        virtual bool onInput(const InputEvent &inputEvent);
        /// (should be) called each time when dimension of element was changed, added and used only with ListView
        /// calls: none, inconsistent api
        /// (should be) called each time when dimension of element was changed
        /// @param oldDim : old bounding box dimensions (item size & position)
        /// @param newDim : new bounding box dimensions (item size & position)
        /// @note TODO should be fixed so that api would be consistent
        virtual bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim);
        /// called on Timer event in application, triggeres timerCallback
        /// @param timer timer element which triggered this action
        /// @param : timer timer element which triggered this action
        virtual bool onTimer(Timer &timer);

        /// @}

        /// function called to add child to item
        /// @param item : pointer to item (widget) that will be added to this item children's
        /// similar approach to QT, adding widget will always succeed.
        virtual void addWidget(Item *item);
        /// function to remove child item from element
        ///  function to remove child item from element
        /// @param item : pointer to item (widget) that will be removed from this item children's
        /// it's recursive for all elements underneath
        /// @attention It doesn't call `delete` please remove item after calling this function
        /// @attention It doesn't call delete please remove item after calling this function
        virtual bool removeWidget(Item *item);
        /// call removeWidget on item and delete on item
        /// @param item : pointer to item (widget) that will be deleted and removed from this item children's
        virtual bool erase(Item *item);
        /// remove all children and destroy them
        virtual void erase();
        /// sets `visible` flag
        virtual void setVisible(bool value);
        /// sets bounding box area (normal) for item
        /// @param area : new bounding box dimensions (area) for item (item size & position)
        virtual void setArea(BoundingBox area);
        /// function for setting bounding box area (normal) on selected axis
        /// @param axis : indicates axis X or Y for operation
        /// @param posOnAxis : new position value for selected axis
        /// @param posOnOrthogonalAxis : new position for axis orthogonal to selected
        /// @param sizeOnAxis : new size for selected axis
        /// @param sizeOnOrthogonalAxis : new size for orthogonal axis to selected
        void setAreaInAxis(Axis axis,
                           uint32_t posOnAxis,
                           uint32_t posOnOrthogonalAxis,
                           uint32_t sizeOnAxis,
                           uint32_t sizeOnOrthogonalAxis);
        /// sets position of element - this is sets area().x and area().y of item
        /// calls onDimensionChanged callback & updateDrawArea for item
        /// @note calls onDimensionChanged callback & updateDrawArea for item
        /// @attention should be bind to area
        virtual void setPosition(const short &x, const short &y);
        virtual void setPosition(const short &val, Axis axis);
        [[nodiscard]] uint16_t getSize(Axis axis) const;
        [[nodiscard]] uint16_t getPosition(Axis axis) const;

        virtual void setMargins(const Margins &value);
        [[nodiscard]] Margins getMargins();

        virtual void setPadding(const Padding &value);
        [[nodiscard]] Padding getPadding() const;

        virtual void setAlignment(const Alignment &value);
        [[nodiscard]] Alignment &getAlignment();
        [[nodiscard]] Alignment getAlignment(Axis axis);
        /// function to calculate absolute position in selected axis in case of alignment
        /// @param axis : selected axis (X or Y)
        /// @param itemSize : size of item on selected axis for this calculation
        /// @return alignment for selected axis.
        [[nodiscard]] virtual uint16_t getAxisAlignmentValue(Axis axis, uint16_t itemSize);

        /// @defgroup size_range_setters Named the same way that are in QT minimum/maximum sizes setters


@@ 235,7 262,6 @@ namespace gui
        void setMaximumWidth(uint32_t w);
        void setMaximumHeight(uint32_t h);
        void setMaximumSize(uint32_t w, uint32_t h);

        void setMinimumSize(uint32_t val, Axis axis);
        void setMinimumSize(uint32_t w, uint32_t h);
        void setMinimumWidth(uint32_t w);


@@ 246,11 272,11 @@ namespace gui
        /// if no parent available - sets size
        /// @return true if handled positively
        virtual auto requestSize(unsigned short request_w, unsigned short request_h) -> Size final;
        /// handle for layouts to implement to resize on demand ( i.e. when it needs to expand after addition/removal of
        /// chars )
        /// handle for layouts to implement to resize on demand ( i.e. when it needs to expand after
        /// addition/removal of chars )
        ///
        /// by default items do not resize of it's childrem so it's safe for them to pass handleRequestSize
        /// straight to setSize. Layout manages size of it's item in range { Area::Min <= size <= Area::Max } so for
        /// @details by default items do not resize of their children so it's safe for them to pass handleRequestSize
        /// straight to setSize. Layout manages size of its item in range { Area::Min <= size <= Area::Max } so in
        /// that case layout should to i.e. store request size and than handle resizes appropriately
        /// i.e. Text => text->requestSize => layout->storeRequest => layout use it in resizes
        /// with this both:


@@ 258,16 284,11 @@ namespace gui
        /// 2. resize requests from UI element
        /// should be handled without infinite loop on resize ( item->setSize -> notify Layout -> layout: item->setSize
        /// )
        ///
        /// @return bool requested size granted {w,h}
        virtual auto handleRequestResize(const Item *, unsigned short request_w, unsigned short request_h) -> Size;

        /// sets size of item
        virtual void setSize(const unsigned short w, const unsigned short h);
        void setSize(uint32_t val, Axis axis);
        /// used in ListView to position element sets area() = WidgetArea(params)
        /// calls onDimensionChanged & updateDrwArea
        /// @attention should be bind to area
        virtual void setBoundingBox(const BoundingBox &new_box);
        /// 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


@@ 276,30 297,45 @@ namespace gui
        /// Implementation of DrawList per Item to be drawn on screen
        /// This is called from buildDrawList before children elements are added
        /// should be = 0;
        /// @param : commands list of commands for renderer to draw elements on screen
        virtual void buildDrawListImplementation(std::list<Command> &commands)
        {}

        /// pre hook function, if set it is executed before building draw command
        /// at Item::buildDrawListImplementation()
        /// @param `commandlist` : commands list of commands for renderer to draw elements on screen
        std::function<void(std::list<Command> &)> preBuildDrawListHook  = nullptr;
        /// post hook function, if set it is executed after building draw command
        /// at Item::buildDrawListImplementation()
        /// @param `commandlist` : commands list of commands for renderer to draw elements on screen
        std::function<void(std::list<Command> &)> postBuildDrawListHook = nullptr;
        /// sets radius of Item box
        /// sets radius for item edges
        /// @note this should be moved to Rect
        virtual void setRadius(int value);

        /// get next navigation item in NavigationDirection
        /// gets next navigation item in NavigationDirection
        /// @param direction : navigation direction (LEFT,RIGHT,UP,DOWN)
        /// @return pointer to next navigation item in selected direction
        virtual Item *getNavigationItem(NavigationDirection direction);
        /// set next navigation item in NavigationDirection
        /// sets navigation item in NavigationDirection
        /// @param direction : navigation direction (LEFT,RIGHT,UP,DOWN)
        /// @param item : pointer to next item for selected direction
        virtual void setNavigationItem(NavigationDirection direction, Item *item);
        /// clear next navigation item in NavigationDirection
        /// clears next navigation item in NavigationDirection
        /// @param direction : navigation direction (LEFT,RIGHT,UP,DOWN)
        virtual void clearNavigationItem(gui::NavigationDirection direction);

        /// item constructor.
        Item();

        Item(Item &) = delete;
        /// item virtual destructor.
        virtual ~Item();

        /// @defgroup inconsistent  inconsistent size/offset accessors and setters
        /// all this elements should be checked for naming/use consistency
        /// all these elements should be checked for naming/use consistency
        /// possibly all of that should be handled via area() (and area should have callback pinned from Item on resize
        /// @{

        void setX(const int32_t x);
        void setY(const int32_t y);
        [[nodiscard]] int32_t getX() const


@@ 319,47 355,64 @@ namespace gui
            return (widgetArea.h);
        }
        /// helper function to show where widget ends in x axis
        /// @return item ends position in X axis
        [[nodiscard]] int32_t offset_w() const
        {
            return getWidth() + widgetArea.x;
        }
        /// helper function to show where widget ends in y axis
        /// @return item ends position in Y axis
        [[nodiscard]] int32_t offset_h() const
        {
            return getHeight() + widgetArea.y;
        }
        /// helper function to show where widget ends in selected axis
        /// @return item ends position in selected axis
        [[nodiscard]] int32_t getOffset(Axis axis) const
        {
            return this->widgetArea.size(axis) + this->widgetArea.pos(axis);
        };
        /// @}

        /// adds timer to gui item
        /// this is needed so that timer for element would live as long as element lives
        /// adds timer to GUI item.
        /// @note this is needed so that timer for element would live as long as element lives.
        /// @details Timers can be attached to Item
        /// in order to pass on an ownership of timer to application/widget which uses its functionalities.
        void attachTimer(std::unique_ptr<Timer> &&timer)
        {
            timers.emplace_back(std::move(timer));
        }

        /// remove timer from item and as a result - destory it
        /// remove timer from item and as a result - destory it.
        void detachTimer(Timer &timer);

        /// simple check function to determine if item is active && visible
        /// simple check function to determine if item is active && visible.
        /// @return true if item is active and visible. Otherwise false.
        inline bool isActive()
        {
            return (activeItem && visible);
        }
        /// @brief
        virtual void accept(GuiVisitor &visitor);

      protected:
        /// 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();
        /// builds draw commands for all of item's children
        /// @param `commandlist` : commands list of commands for renderer to draw elements on screen
        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;
    };

      private:
        /// list of attached timers to item.
        std::list<std::unique_ptr<Timer>> timers;
    };
    /// gets navigation direction (LEFT,RIGHT,UP,DOWN) based on incoming input event
    /// @param[in] evt : input event e.g. key pressed
    NavigationDirection inputToNavigation(const InputEvent &evt);
    /// checks whether input event is related to GUI navigation directions (LEFT,RIGHT,UP,DOWN)
    /// @param evt : input event e.g. key pressed
    bool isInputNavigation(const InputEvent &evt);
} /* namespace gui */