def gather_hovered(self, menu, hovered_widgets):
        """Gather all menu items over which the mouse hovers.

        menu (either a menu.main.MenuManager instance or a
              menu.submenu.main.Menu instance)
            contains children which are either Menu instances
            and/or menu.command.Command instances.
        hovered_widgets (list)
            list of hovered widgets found so far, which is
            updated recursively as we travel through the
            active branch. The way we travel the branch and
            update the list makes it so the contents are
            always sorted from the widgets nearest to the
            MenuManager instance (root) to the ones farthest
            from it. This ordering is intended and needed
            for the use for which this list was designed.
            The list might be empty if no hovered widget
            was found.

        As an additional administrative task, we unhighlight
        widgets over which the mouse doesn't hover, as long
        as they are not expanded.

        The pygame.Rect from the 'rect' attribute of the
        menu is used for the collision. Collision with the
        pygame.Rect stored in the 'body' attribute is also
        checked in some circunstance to handle admin tasks.
        """
        ### alias mouse position
        mouse_pos = self.mouse_pos

        ### create an 'expanded_child' variable to hold
        ### the expanded child of the menu if we detect
        ### one while iterating
        expanded_child = None

        ### also create a flag to determine whether any of
        ### the children have collided with the mouse
        any_child_collided = 0

        ### iterate over the children, checking if they are
        ### hovered or not and performing setups and admin
        ### tasks as needed

        for child in menu.children:

            ## evaluate conditions

            is_top_command = self.is_top_command(child)
            is_top_menu = self.is_top_menu(child)

            collided = child.rect.collidepoint(mouse_pos)

            try:
                is_expanded = child.is_expanded
            except AttributeError:
                is_expanded = False

            ## disregard collision if the menu is scrollable
            ## and the mouse doesn't hover the scroll area

            if menu.is_scrollable() and not menu.scroll_area.collidepoint(mouse_pos):
                collided = 0

            ## admin task: update flag
            any_child_collided = max(any_child_collided, collided)

            ## if a collision was detected, check the
            ## preliminary conditions for the widget to be
            ## added to the hovered widget list

            if collided:

                # if the widget is either a top command or
                # a top menu or, in case it is neither, its
                # top menu is active and its direct parent
                # is expanded we append the child to the
                # list of hovered widgets

                if (
                    is_top_command
                    or is_top_menu
                    or (self.top_menu_is_active(child) and child.parent.is_expanded)
                ):
                    hovered_widgets.append(child)

            ## if no collision was detected, though, just
            ## unhighlight the child if it is not expanded
            ## (admin task)

            else:

                if not is_expanded:
                    child.unhighlight()

            ## regardless of whether the child is hovered
            ## by the mouse or not, if it is expanded,
            ## store a reference to it
            if is_expanded:
                expanded_child = child

        ### extra measure in case no collision is detected
        ### for any child

        if not any_child_collided:

            ## in case we the menu is not self (that is,
            ## not the MenuManager instance) we check the
            ## rect in the menu's body for collision and if
            ## there's one, we consider the menu itself as
            ## the hovered widget;
            ##
            ## this is to prevent a submenu to loose focus
            ## to the one behind it when hovering only arrows
            ## (since the arrows are not checked for
            ## collision here);
            ##
            ## thus, even if no child is hovered by the
            ## mouse, as long as the cursor is in the body
            ## of the menu, the menu is kept expanded;

            if menu is not self:

                if menu.body.rect.collidepoint(mouse_pos):
                    hovered_widgets.append(menu)

        ### now we treat the expanded_child object if there
        ### is one; here we further check the children of the
        ### expanded child recursively for hovered widgets,
        ### extending the hovered_widgets variable with the
        ### return value (which might or not be an empty
        ### list)

        if expanded_child:

            hovered_on_child = self.gather_hovered(expanded_child, [])
            hovered_widgets.extend(hovered_on_child)

        ### finally return the hovered widgets list
        return hovered_widgets
Gather all menu items over which the mouse hovers.

        menu (either a menu.main.MenuManager instance or a
              menu.submenu.main.Menu instance)
            contains children which are either Menu instances
            and/or menu.command.Command instances.
        hovered_widgets (list)
            list of hovered widgets found so far, which is
            updated recursively as we travel through the
            active branch. The way we travel the branch and
            update the list makes it so the contents are
            always sorted from the widgets nearest to the
            MenuManager instance (root) to the ones farthest
            from it. This ordering is intended and needed
            for the use for which this list was designed.
            The list might be empty if no hovered widget
            was found.

        As an additional administrative task, we unhighlight
        widgets over which the mouse doesn't hover, as long
        as they are not expanded.

        The pygame.Rect from the 'rect' attribute of the
        menu is used for the collision. Collision with the
        pygame.Rect stored in the 'body' attribute is also
        checked in some circunstance to handle admin tasks.
        
nodezator/menu/hover.py