def build_form_widgets(self):
        """Build widgets to hold settings for edition."""
        ### create special list to hold widgets
        widgets = self.widgets = List2D()

        ### define an initial topleft relative to the
        ### topleft corner of the form 'rect'
        topleft = self.rect.move(5, 5).topleft

        ### instantiate a caption for the form

        caption_label = Object2D.from_surface(
            surface=(
                render_text(
                    text="Set and start session playing",
                    border_thickness=2,
                    border_color=(TEXT_SETTINGS["foreground_color"]),
                    **TEXT_SETTINGS,
                )
            ),
            coordinates_name="topleft",
            coordinates_value=topleft,
        )

        widgets.append(caption_label)

        ### update the topleft to a value a bit below
        ### the bottomleft corner of the widgets already
        ### in the versatile list
        topleft = widgets.rect.move(0, 20).bottomleft

        ### instantiate widgets for filepath to play

        ## filepath label

        new_file_label = Object2D.from_surface(
            surface=render_text(
                text="File with input data to play:", **TEXT_SETTINGS
            ),
            coordinates_name="topleft",
            coordinates_value=topleft,
        )

        widgets.append(new_file_label)

        ## filepath change button

        topleft = new_file_label.rect.move(0, 5).bottomleft

        change_filepath_button = Button.from_text(
            text="Change path",
            command=self.change_filepath,
            coordinates_name="topleft",
            coordinates_value=topleft,
            **BUTTON_SETTINGS,
        )

        draw_depth_finish(change_filepath_button.image)

        widgets.append(change_filepath_button)

        ## chosen filepath label

        midleft = change_filepath_button.rect.move(5, 0).midright

        self.filepath_label = Label(
            text="(no path selected)",
            name="input_data_path",
            max_width=485,
            ellipsis_at_end=False,
            coordinates_name="midleft",
            coordinates_value=midleft,
            **TEXT_SETTINGS,
        )

        widgets.append(self.filepath_label)

        ### update the topleft to a value a bit below
        ### the bottomleft corner of the widgets already
        ### in the versatile list
        topleft = widgets.rect.move(0, 20).bottomleft

        ### instantiate widgets for playback speed

        speed_label = Object2D.from_surface(
            render_text("Speed (frames/second):", **TEXT_SETTINGS),
            coordinates_name="topleft",
            coordinates_value=topleft,
        )

        widgets.append(speed_label)

        ## entry to pick speed

        midleft = speed_label.rect.move(5, 0).midright

        self.speed_entry = IntFloatEntry(
            value=FPS,
            min_value = 0,
            numeric_classes_hint='int_float',
            loop_holder=self,
            command=self.check_speed_button_surfs,
            width=100,
            coordinates_name="midleft",
            coordinates_value=midleft,
        )

        widgets.append(self.speed_entry)

        ## extra buttons for speed

        midleft = self.speed_entry.rect.move(10, 0).midright

        set_speed = self.speed_entry.set

        for text, speed in (
            ("0.25x", FPS//4),
            ("0.5x", FPS//2),
            ("1x", FPS),
            ("2x", FPS*2),
            ("4x", FPS*4),
            ("max/uncapped", 0),
        ):

            speed_button = Button.from_text(
                text=text,
                command=partial(set_speed, speed),
                coordinates_name="midleft",
                coordinates_value=midleft,
                **BUTTON_SETTINGS,
            )

            highlighted_surf = (
                render_text(
                    text=text,
                    **HIGHLIGHTED_SPEED_BUTTON_SETTINGS,
                )
            )

            SPEED_TO_BUTTON[speed] = speed_button

            SPEED_BUTTON_SURF_MAP[speed_button] = (
                speed_button.image, highlighted_surf
            )

            midleft = speed_button.rect.midright

            draw_depth_finish(speed_button.image)

            widgets.append(speed_button)

        ### update speed button surfs
        self.check_speed_button_surfs()

        ### update the topleft to a value a bit below
        ### the bottomleft corner of the widgets already
        ### in the versatile list
        topleft = widgets.rect.move(0, 20).bottomleft

        ### create and store behaviour for exiting the form
        ### (equivalent to setting the 'running' flag to False)
        self.cancel = partial(setattr, self, "running", False)

        ### create, position and store form related buttons

        ## start button

        self.start_button = Button.from_text(
            text="Start playing session",
            command=self.trigger_playing,
            **BUTTON_SETTINGS,
        )

        draw_depth_finish(self.start_button.image)

        self.start_button.rect.bottomright = self.rect.move(-10, -10).bottomright

        ## cancel button

        self.cancel_button = Button.from_text(
            text="Cancel",
            command=self.cancel,
            **BUTTON_SETTINGS,
        )

        draw_depth_finish(self.cancel_button.image)

        self.cancel_button.rect.midright = self.start_button.rect.move(-5, 0).midleft

        ## store
        widgets.extend((self.cancel_button, self.start_button))
Build widgets to hold settings for edition.
nodezator/editing/playback/play.py