def redraw_scrollbar(self):
        """
        Redraws the 'scrollbar' portion of the whole UI element. Called when we change the visible percentage.
        """
        self.sliding_button.kill()

        self.scrollable_height = (self.rect.height - (2 * self.button_height) -
                                  (2 * self.border_width) -
                                  (2 * self.shadow_width))
        scroll_bar_height = int(self.scrollable_height *
                                self.visible_percentage)
        self.sliding_rect_position.y = (
            self.rect.y + self.button_height + self.shadow_width +
            self.border_width +
            (self.start_percentage * self.scrollable_height))
        self.sliding_button = ui_button.UIButton(pygame.Rect(
            self.sliding_rect_position,
            (self.rect.width - (2 * self.border_width) -
             (2 * self.shadow_width), scroll_bar_height)),
                                                 '',
                                                 self.ui_manager,
                                                 container=self.ui_container,
                                                 starting_height=2,
                                                 parent_element=self,
                                                 object_id="#sliding_button")
    def __init__(self, relative_rect: pygame.Rect,
                 visible_percentage: float,
                 manager: ui_manager.UIManager,
                 container: ui_container.UIContainer = None,
                 parent_element: UIElement = None,
                 object_id: Union[str, None] = None):

        new_element_ids, new_object_ids = self.create_valid_ids(parent_element=parent_element,
                                                                object_id=object_id,
                                                                element_id='vertical_scroll_bar')
        super().__init__(relative_rect, manager, container,
                         layer_thickness=1, starting_height=1,
                         element_ids=new_element_ids,
                         object_ids=new_object_ids)

        self.button_height = 20
        self.background_colour = self.ui_theme.get_colour(self.object_ids, self.element_ids, 'dark_bg')

        self.border_width = 0
        border_width_string = self.ui_theme.get_misc_data(self.object_ids, self.element_ids, 'border_width')
        if border_width_string is not None:
            self.border_width = int(border_width_string)

        self.shadow_width = 0
        shadow_width_string = self.ui_theme.get_misc_data(self.object_ids, self.element_ids, 'shadow_width')
        if shadow_width_string is not None:
            self.shadow_width = int(shadow_width_string)

        self.background_colour = self.ui_theme.get_colour(self.object_ids, self.element_ids, 'dark_bg')
        self.border_colour = self.ui_theme.get_colour(self.object_ids, self.element_ids, 'normal_border')

        if self.shadow_width > 0:
            self.image = self.ui_manager.get_shadow(self.rect.size)
        else:
            self.image = pygame.Surface(self.rect.size, flags=pygame.SRCALPHA)

        border_rect = pygame.Rect((self.shadow_width, self.shadow_width),
                                  (self.rect.width - (2 * self.shadow_width),
                                   self.rect.height - (2 * self.shadow_width)))
        if self.border_width > 0:
            self.image.fill(self.border_colour,
                            border_rect)

        relative_background_rect = pygame.Rect((self.border_width + self.shadow_width,
                                                self.border_width + self.shadow_width),
                                               (border_rect.width - (2 * self.border_width),
                                                border_rect.height - (2 * self.border_width)))

        background_rect = pygame.Rect((relative_background_rect.x + relative_rect.x,
                                       relative_background_rect.y + relative_rect.y),
                                      relative_background_rect.size)
        self.image.fill(self.background_colour,
                        relative_background_rect)

        self.top_button = ui_button.UIButton(pygame.Rect(background_rect.topleft,
                                                         (background_rect.width,
                                                          self.button_height)),
                                             '▲', self.ui_manager,
                                             container=self.ui_container,
                                             starting_height=2,
                                             parent_element=self,
                                             object_id="#top_button")

        bottom_button_y = background_rect.y + background_rect.height - self.button_height
        self.bottom_button = ui_button.UIButton(pygame.Rect((background_rect.x,
                                                             bottom_button_y),
                                                            (background_rect.width,
                                                             self.button_height)),
                                                '▼', self.ui_manager,
                                                container=self.ui_container,
                                                starting_height=2,
                                                parent_element=self,
                                                object_id="#bottom_button")

        self.visible_percentage = max(0.0, min(visible_percentage, 1.0))
        self.start_percentage = 0.0

        self.sliding_rect_position = pygame.math.Vector2(background_rect.x,
                                                         background_rect.y + self.button_height)

        self.scrollable_height = background_rect.height - (2 * self.button_height)
        scroll_bar_height = int(self.scrollable_height * self.visible_percentage)
        self.sliding_button = ui_button.UIButton(pygame.Rect(self.sliding_rect_position,
                                                             (background_rect.width,
                                                              scroll_bar_height)),
                                                 '', self.ui_manager,
                                                 container=self.ui_container,
                                                 starting_height=2,
                                                 parent_element=self,
                                                 object_id="#sliding_button")

        self.sliding_button.set_hold_range((100, background_rect.height))

        self.scroll_position = 0.0
        self.top_limit = 0.0
        self.bottom_limit = self.scrollable_height

        self.grabbed_slider = False
        self.starting_grab_y_difference = 0

        self.has_moved_recently = False

        self.scroll_wheel_up = False
        self.scroll_wheel_down = False
    def __init__(self,
                 relative_rect: pygame.Rect,
                 visible_percentage: float,
                 manager: ui_manager.UIManager,
                 container: ui_container.UIContainer = None,
                 parent_element: UIElement = None,
                 object_id: Union[str, None] = None):

        new_element_ids, new_object_ids = self.create_valid_ids(
            parent_element=parent_element,
            object_id=object_id,
            element_id='vertical_scroll_bar')
        super().__init__(relative_rect,
                         manager,
                         container,
                         layer_thickness=1,
                         starting_height=1,
                         element_ids=new_element_ids,
                         object_ids=new_object_ids)

        self.button_height = 20
        self.scroll_position = 0.0
        self.top_limit = 0.0
        self.starting_grab_y_difference = 0
        self.visible_percentage = max(0.0, min(visible_percentage, 1.0))
        self.start_percentage = 0.0

        self.grabbed_slider = False
        self.has_moved_recently = False
        self.scroll_wheel_up = False
        self.scroll_wheel_down = False

        self.background_colour = None
        self.border_colour = None
        self.border_width = None
        self.shadow_width = None

        self.drawable_shape = None
        self.shape_type = 'rectangle'
        self.shape_corner_radius = None

        self.background_rect = None
        self.border_rect = None
        self.relative_background_rect = None

        self.scrollable_height = None  # type: Union[None, int, float]
        self.bottom_limit = None
        self.sliding_rect_position = None

        self.top_button = None
        self.bottom_button = None
        self.sliding_button = None

        self.rebuild_from_changed_theme_data()

        self.top_button = ui_button.UIButton(pygame.Rect(
            self.background_rect.topleft,
            (self.background_rect.width, self.button_height)),
                                             '▲',
                                             self.ui_manager,
                                             container=self.ui_container,
                                             starting_height=2,
                                             parent_element=self,
                                             object_id="#top_button")

        bottom_button_y = self.background_rect.y + self.background_rect.height - self.button_height
        self.bottom_button = ui_button.UIButton(pygame.Rect(
            (self.background_rect.x, bottom_button_y),
            (self.background_rect.width, self.button_height)),
                                                '▼',
                                                self.ui_manager,
                                                container=self.ui_container,
                                                starting_height=2,
                                                parent_element=self,
                                                object_id="#bottom_button")

        scroll_bar_height = int(self.scrollable_height *
                                self.visible_percentage)
        self.sliding_button = ui_button.UIButton(pygame.Rect(
            (int(self.sliding_rect_position[0]),
             int(self.sliding_rect_position[1])),
            (self.background_rect.width, scroll_bar_height)),
                                                 '',
                                                 self.ui_manager,
                                                 container=self.ui_container,
                                                 starting_height=2,
                                                 parent_element=self,
                                                 object_id="#sliding_button")

        self.sliding_button.set_hold_range((100, self.background_rect.height))