Source code for pygame_menu.widgets.widget.progressbar

"""
pygame-menu
https://github.com/ppizarror/pygame-menu

PROGRESS BAR
Progress bar widget.

License:
-------------------------------------------------------------------------------
The MIT License (MIT)
Copyright 2017-2021 Pablo Pizarro R. @ppizarror

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------------
"""

__all__ = [

    # Class
    'ProgressBar',

    # Types
    'ProgressBarTextFormatType'

]

import pygame
import pygame_menu

from pygame_menu.font import FontType, assert_font
from pygame_menu.locals import ALIGN_LEFT, ALIGN_CENTER
from pygame_menu.utils import assert_color, assert_vector, make_surface, \
    is_callable, assert_alignment, parse_padding
from pygame_menu.widgets.core.widget import Widget, WidgetTransformationNotImplemented

from pygame_menu._types import Any, CallbackType, Optional, ColorType, NumberType, \
    Tuple2IntType, NumberInstance, ColorInputType, EventVectorType, Callable, \
    PaddingType, Tuple4IntType

ProgressBarTextFormatType = Callable[[NumberType], str]


# noinspection PyMissingOrEmptyDocstring
[docs]class ProgressBar(Widget): """ Progress bar widget, offers a bar that accepts a percentage from ``0`` to ``100``. .. note:: ProgressBar only accepts translation transformation. :param title: Progressbar title :param progressbar_id: ProgressBar ID :param default: Default value of the progressbar, from ``0`` to ``100`` :param width: Progress bar width in px :param onselect: Function when selecting the widget :param box_background_color: Background color of the box :param box_border_color: Border color of the box :param box_border_width: Border width of the box in px :param box_margin: Box margin on x-axis and y-axis (x, y) respect to the title of the widget in px :param box_progress_color: Box progress color :param box_progress_padding: Box progress padding :param progress_text_align: Align of the progress text, can be CENTER, LEFT or RIGHT. See :py:mod:`pygame_menu.locals` :param progress_text_enabled: Enables the progress text over box :param progress_text_font: Progress font. If ``None`` uses the same as the widget font :param progress_text_font_color: Progress font color. If ``None`` uses the same as the widget font :param progress_text_font_hfactor: Height factor of the font height relative to the widget font height :param progress_text_format: Format function of the progress text, which considers as input the progress value (0-100) :param progress_text_margin: Margin of the progress box on x-axis and y-axis in px :param progress_text_placeholder: Placeholder of the progress text, which considers as format the output of ``progress_text_format`` :param args: Optional arguments for callbacks :param kwargs: Optional keyword arguments """ _box: 'pygame.Surface' _box_background_color: ColorType _box_border_color: ColorType _box_border_width: int _box_height: int _box_margin: Tuple2IntType _box_pos: int _box_progress_color: ColorType _box_progress_padding: Tuple4IntType _progress: NumberType _progress_font: FontType _progress_text_align: str _progress_text_enabled: bool _progress_text_font: Optional[FontType] _progress_text_font_color: ColorType _progress_text_font_height: int _progress_text_font_height_factor: float _progress_text_format: ProgressBarTextFormatType _progress_text_margin: Tuple2IntType _progress_text_placeholder: str _width: int def __init__( self, title: Any, progressbar_id: str = '', default: NumberType = 0, width: int = 150, onselect: CallbackType = None, box_background_color: ColorInputType = (255, 255, 255), box_border_color: ColorInputType = (0, 0, 0), box_border_width: int = 1, box_margin: Tuple2IntType = (25, 0), box_progress_color: ColorInputType = (0, 255, 0), box_progress_padding: PaddingType = (1, 1), progress_text_align: str = ALIGN_CENTER, progress_text_enabled: bool = True, progress_text_font: Optional[FontType] = None, progress_text_font_color: ColorInputType = (0, 0, 0), progress_text_font_hfactor: float = 0.8, progress_text_format: ProgressBarTextFormatType = lambda x: str(round(x, 1)), progress_text_margin: Tuple2IntType = (0, 0), progress_text_placeholder: str = '{0} %', *args, **kwargs ) -> None: super(ProgressBar, self).__init__( args=args, kwargs=kwargs, onselect=onselect, title=title, widget_id=progressbar_id ) # Check the value assert isinstance(default, NumberInstance) assert 0 <= default <= 100, 'default value must range from 0 to 100' # Check fonts if progress_text_font is not None: assert_font(progress_text_font) assert isinstance(progress_text_font_hfactor, NumberInstance) assert progress_text_font_hfactor > 0, \ 'progress text font height factor must be greater than zero' # Check colors box_background_color = assert_color(box_background_color) box_border_color = assert_color(box_border_color) box_progress_color = assert_color(box_progress_color) progress_text_font_color = assert_color(progress_text_font_color) # Check dimensions and sizes assert isinstance(box_border_width, int) assert box_border_width >= 0, \ 'box border width must be equal or greater than zero' assert_vector(box_margin, 2, int) assert_vector(progress_text_margin, 2, int) assert isinstance(width, int) assert width > 0, 'width must be greater than zero' box_progress_padding = parse_padding(box_progress_padding) self._box_progress_padding = box_progress_padding # Check progress text assert isinstance(progress_text_enabled, bool) assert is_callable(progress_text_format) assert isinstance(progress_text_format(0), str) assert isinstance(progress_text_placeholder, str) assert_alignment(progress_text_align) # Store properties self._default_value = default self._box_background_color = box_background_color self._box_border_color = box_border_color self._box_border_width = box_border_width self._box_margin = box_margin self._box_progress_color = box_progress_color self._progress = default self._progress_text_align = progress_text_align self._progress_text_enabled = progress_text_enabled self._progress_text_font = progress_text_font self._progress_text_font_color = progress_text_font_color self._progress_text_font_height = 0 self._progress_text_font_height_factor = progress_text_font_hfactor self._progress_text_format = progress_text_format self._progress_text_margin = progress_text_margin self._progress_text_placeholder = progress_text_placeholder self._width = width
[docs] def set_value(self, value: NumberType) -> None: assert isinstance(value, NumberInstance), 'progress value must be numeric' assert 0 <= value <= 100, 'value must be between 0 and 100' self._progress = value self._render()
def scale(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def resize(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def set_max_width(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def set_max_height(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def rotate(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def flip(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented()
[docs] def get_value(self) -> NumberType: return self._progress
def _apply_font(self) -> None: if self._progress_text_font is None: self._progress_text_font = self._font_name self._progress_text_font_height = int(self._font_size * self._progress_text_font_height_factor) self._progress_font = pygame_menu.font.get_font( self._progress_text_font, self._progress_text_font_height ) self._box_height = self._font_render_string('TEST').get_height() def _draw(self, surface: 'pygame.Surface') -> None: # Draw title surface.blit(self._surface, (self._rect.x, self._rect.y)) # Draw box box_rect = self._box.get_rect() box_rect.x += self._rect.x + self._box_margin[0] + self._box_pos box_rect.y += self._rect.y + self._box_margin[1] surface.blit(self._box, box_rect) # Draw box border if self._box_border_width > 0: pygame.draw.rect(surface, self._box_border_color, box_rect, self._box_border_width) def _render(self) -> Optional[bool]: if not hasattr(self, '_progress_font'): return False if not self._render_hash_changed( self._selected, self._title, self._visible, self.readonly, self._progress): return True # Create basic title self._surface = self._render_string(self._title, self.get_font_color_status()) self._rect.width, self._rect.height = self._surface.get_size() # Create box self._box = make_surface(self._width, self._box_height, fill_color=self._box_background_color) box_progress = make_surface(int(self._width * self._progress / 100), self._box_height - self._box_progress_padding[0] - self._box_progress_padding[2], fill_color=self._box_progress_color) self._box.blit(box_progress, (self._box_progress_padding[1], self._box_progress_padding[0])) self._box_pos = self._rect.width # Create progress text text = self._progress_font.render( self._progress_text_placeholder.format(self._progress_text_format(self._progress)), self._font_antialias, self._progress_text_font_color ) text_y = int((self._box_height - text.get_height()) / 2) if self._progress_text_align == ALIGN_LEFT: text_x = self._box_progress_padding[1] elif self._progress_text_align == ALIGN_CENTER: text_x = int((self._width - text.get_width()) / 2) else: text_x = self._width - self._box_progress_padding[3] - text.get_width() text_x += self._progress_text_margin[0] text_y += self._progress_text_margin[1] if self._progress_text_enabled: self._box.blit(text, (text_x, text_y)) # Update maximum rect height self._rect.height = max(self._rect.height, self._box.get_height()) self._rect.width += self._width + self._box_margin[0] # Finals self.force_menu_surface_update()
[docs] def update(self, events: EventVectorType) -> bool: self.apply_update_callbacks(events) return False