def create_and_show_dialog(

        self,

        message,
        buttons=None,
        level_name="info",
        unhighlighter_obj=None,

        ## dialog clamping and anchoring

        clamping_rect=None,
        anchor_rect=None,
        dialog_pos_from="center",
        dialog_pos_to="center",
        dialog_offset_by=(0, 0),

        ## flag
        dismissable=True,

    ):
        """Create a dialog with/out buttons.

        Parameters
        ==========
        message (string)
            message to be displayed on top of the dialog
            box.
        level_name (string)
            indicates the level of severity of the dialog
            message; available levels are 'info', 'warning',
            'error' and 'critical'. We don't work with
            messages of level 'debug', since they are not
            relevant for users and thus don't appear in
            dialogs (they must instead be logged elsewhere);
            this level name is used as a key to pick an
            appropriate icon to convey the severity to the
            user.
        buttons (iterable of 2-tuples)
            each 2-tuple represents a button. The first
            value is a string for the button text and the
            second value is an arbitrary value to be
            returned by that button, if clicked.
        unhighlighter_obj (obj with draw method or None)
            object used to unhighlight what's behind the
            dialog box.
        """
        ### store dismissable flag
        self.dismissable = dismissable

        ### ensure screen rect is used if specific rects
        ### are None

        if clamping_rect is None:
            clamping_rect = SCREEN_RECT

        if anchor_rect is None:
            anchor_rect = SCREEN_RECT

        ### create objects and their surfaces/rects

        self.create_message(message)

        self.create_buttons(buttons)

        self.create_and_position_dialog(
            level_name,
            clamping_rect,
            anchor_rect,
            dialog_pos_from,
            dialog_pos_to,
            dialog_offset_by,
        )

        self.rect_sized_semitransp_obj = Object2D.from_surface(
            surface=(
                render_rect(
                    *self.rect.size,
                    (*CONTRAST_LAYER_COLOR, 130),
                )
            ),
            coordinates_name="topleft",
            coordinates_value=self.rect.topleft,
        )

        ### store a default value
        self.value = None

        ### store button references to rotate with keyboard
        self.buttons_deque = deque(self.buttons)

        ### store rect used to outline currently selected button
        self.rotate_selection(0, redraw=False)

        ### blit a semitransparent surface in the canvas
        ### to increase constrast between the dialog
        ### and whatever is behind it (making what's behind
        ### appear unhighlighted)

        ## if an object was received, draw it
        if unhighlighter_obj is not None:
            unhighlighter_obj.draw()

        ## otherwise perform a custom operation to draw
        ## such surface

        else:
            blit_on_screen(UNHIGHLIGHT_SURF_MAP[SCREEN_RECT.size], (0, 0))

        ### draw objects created
        self.draw_once()

        ### loop
        self.loop()

        ### blit semitransparent obj (make the dialog
        ### appear unhighlighted; this is important in
        ### case the portions of the screen showing the
        ### dialog aren't updated by the next object
        ### managing the screen once we leave this
        ### method)
        self.rect_sized_semitransp_obj.draw()

        ### free up memory from text objects and buttons
        self.free_up_memory()

        ### finally return the value picked
        return self.value
Create a dialog with/out buttons.

        Parameters
        ==========
        message (string)
            message to be displayed on top of the dialog
            box.
        level_name (string)
            indicates the level of severity of the dialog
            message; available levels are 'info', 'warning',
            'error' and 'critical'. We don't work with
            messages of level 'debug', since they are not
            relevant for users and thus don't appear in
            dialogs (they must instead be logged elsewhere);
            this level name is used as a key to pick an
            appropriate icon to convey the severity to the
            user.
        buttons (iterable of 2-tuples)
            each 2-tuple represents a button. The first
            value is a string for the button text and the
            second value is an arbitrary value to be
            returned by that button, if clicked.
        unhighlighter_obj (obj with draw method or None)
            object used to unhighlight what's behind the
            dialog box.
        
nodezator/dialog.py