diff --git a/examples.py b/examples.py index 364a696..0017c3c 100644 --- a/examples.py +++ b/examples.py @@ -7,7 +7,8 @@ from progressbar import AnimatedMarker, Bar, BouncingBar, Counter, ETA, \ AdaptiveETA, FileTransferSpeed, FormatLabel, Percentage, \ ProgressBar, ReverseBar, RotatingMarker, \ - SimpleProgress, Timer, UnknownLength + SimpleProgress, Timer, UnknownLength, \ + BrailleBouncer examples = [] def example(fn): @@ -222,6 +223,16 @@ def example20(): pbar.update(i + 1) pbar.finish() + +@example +def example21(): + """Progress bar with braille bouncer widget""" + widgets = [FormatLabel('Braille Bouncer: value %(value)d - '), BrailleBouncer()] + pbar = ProgressBar(widgets=widgets) + for _ in pbar((i for i in range(180))): + time.sleep(0.05) + + if __name__ == '__main__': try: for example in examples: example() diff --git a/progressbar/widgets.py b/progressbar/widgets.py index dd3c6ef..2019e81 100644 --- a/progressbar/widgets.py +++ b/progressbar/widgets.py @@ -357,3 +357,42 @@ def update(self, pbar, width): if not self.fill_left: rpad, lpad = lpad, rpad return '%s%s%s%s%s' % (left, lpad, marker, rpad, right) + + +class BrailleBouncer(Bar): + def __init__(self, marker='\u28FF', left='\u2847', right='\u28B8', fill=' ', fill_left=False, finish_animation=True): + super().__init__(marker, left, right, fill, fill_left) + self._charidx = -1 + self._inverse_animation = False + + def update(self, pbar, width): + """Updates the progress bar and bouncer animation.""" + + chars = ['\u28C0', '\u28E4', '\u28F6', '\u28FF', '\u283F', '\u281B', '\u2809'] + chars_reverse = list(reversed(chars)) + + left, marker, right = (format_updatable(i, pbar) for i in + (self.left, self.marker, self.right)) + + width -= len(left) + len(right) + + if pbar.finished: + return '%s%s%s' % (left, width * marker, right) + + position = int(pbar.currval % (width * 2 - 1)) + if position > width: position = width * 2 - position + lpad = self.fill * (position - 1) + rpad = self.fill * (width - len(marker) - len(lpad)) + + # Swap if we want to bounce the other way + if not self.fill_left: rpad, lpad = lpad, rpad + + self._charidx += 1 + if self._charidx % 7 == 0: + self._charidx += 1 + self._inverse_animation = not self._inverse_animation + + if self._inverse_animation: + return '%s%s%s%s%s' % (left, lpad, chars[(self._charidx - 1) % 7], rpad, right) + else: + return '%s%s%s%s%s' % (left, lpad, chars_reverse[((self._charidx - 1) % 7)], rpad, right)