Skip to content

Commit f1767bc

Browse files
committed
Refactor more common code to the core class
1 parent da82b42 commit f1767bc

File tree

3 files changed

+132
-146
lines changed

3 files changed

+132
-146
lines changed

adafruit_progressbar/__init__.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -472,22 +472,109 @@ def get_value_ratio(self, value: Union[int, float]) -> float:
472472

473473
return (float(value) - self.minimum) / (self.maximum - self.minimum)
474474

475+
@classmethod
476+
def _get_value_sizes(cls, _old_ratio: float, _new_ratio: float) -> Tuple[int, int]:
477+
return 0, 0
478+
479+
def _get_ratios(
480+
self, _old_value: Union[int, float], _new_value: Union[int, float]
481+
) -> Tuple[float, float]:
482+
return self.get_value_ratio(_old_value), self.get_value_ratio(_new_value)
483+
484+
def _adjust_size_for_range_limits(
485+
self, _new_value_size: int, _new_value: Union[int, float]
486+
) -> int:
487+
# If we have *ANY* value other than "zero" (minimum), we should
488+
# have at least one element showing
489+
if _new_value_size == 0 and _new_value > self.minimum:
490+
_new_value_size = 1
491+
492+
# Conversely, if we have *ANY* value other than 100% (maximum),
493+
# we should NOT show a full bar.
494+
if _new_value_size == self.fill_height() and _new_value < self.maximum:
495+
_new_value_size -= 1
496+
497+
return _new_value_size
498+
499+
def _get_sizes_min_max(self) -> Tuple[int, int]:
500+
return 0, min(self.fill_width(), self.fill_height())
501+
502+
@classmethod
503+
def _invert_fill_direction(cls) -> bool:
504+
return False
505+
506+
def _get_horizontal_fill(
507+
self, _start: int, _end: int, _incr: int
508+
) -> Tuple[int, int, int]:
509+
return 0, self.fill_width(), 1 # Subclass must return values
510+
511+
def _get_vertical_fill(
512+
self, _start: int, _end: int, _incr: int
513+
) -> Tuple[int, int, int]:
514+
return 0, self.fill_height(), 1 # Subclass must return values
515+
516+
# pylint: disable=too-many-locals
475517
def _render(
476518
self,
477519
_old_value: Union[int, float],
478520
_new_value: Union[int, float],
479521
_progress_value: float,
480522
) -> None:
481-
"""The method called when the display needs to be updated. This method
482-
can be overridden in child classes to handle the graphics appropriately.
523+
"""
524+
Does the work of actually creating the graphical representation of
525+
the value (percentage, aka "progress") to be displayed.
483526
484-
:param _old_value: The value from which we're updating
527+
:param _old_value: The previously displayed value
485528
:type _old_value: int/float
486-
:param _new_value: The value to which we're updating
529+
:param _new_value: The new value to display
487530
:type _new_value: int/float
488-
:param _progress_value: The value of the progress, or ratio between the new value and the
489-
maximum value
531+
:param _progress_value: The value to display, as a percentage, represented
532+
by a float from 0.0 to 1.0 (0% to 100%)
490533
:type _progress_value: float
491-
492534
:rtype: None
493535
"""
536+
537+
_prev_ratio, _new_ratio = self._get_ratios(_old_value, _new_value)
538+
_old_value_size, _new_value_size = self._get_value_sizes(
539+
_prev_ratio, _new_ratio
540+
)
541+
542+
# Adjusts for edge cases, such as 0-width non-zero value, or 100% width
543+
# non-maximum values
544+
_new_value_size = self._adjust_size_for_range_limits(
545+
_new_value_size, _new_value
546+
)
547+
_render_offset = self.margin_size + self.border_thickness
548+
549+
# Default values for increasing value
550+
_color = 2
551+
_incr = 1
552+
_start = max(_old_value_size + _render_offset, _render_offset)
553+
_end = max(_new_value_size, 0) + _render_offset
554+
555+
if _old_value_size >= _new_value_size:
556+
# Override defaults to be decreasing
557+
_color = 0 # Clear
558+
_incr = -1 # Iterate range downward
559+
_start = max(_old_value_size + _render_offset, _render_offset)
560+
_end = max(_new_value_size + _render_offset, _render_offset) - 1
561+
# If we're setting to minimum, make sure we're clearing by
562+
# starting one "bar" higher
563+
if _new_value == self.minimum:
564+
_start += 1
565+
566+
if self._invert_fill_direction():
567+
_ref_pos = self.widget_height - 1
568+
_end = _ref_pos - _end # Those pesky "off-by-one" issues
569+
_start = _ref_pos - _start
570+
_incr = -1 if _start > _end else 1
571+
_color = 0 if _old_value > _new_value else 2
572+
573+
vert_start, vert_end, vert_incr = self._get_vertical_fill(_start, _end, _incr)
574+
horiz_start, horiz_end, horiz_incr = self._get_horizontal_fill(
575+
_start, _end, _incr
576+
)
577+
578+
for vertical_position in range(vert_start, vert_end, vert_incr):
579+
for horizontal_position in range(horiz_start, horiz_end, horiz_incr):
580+
self._bitmap[horizontal_position, vertical_position] = _color

adafruit_progressbar/horizontalprogressbar.py

Lines changed: 19 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ def __init__(
120120
direction: HorizontalFillDirection = HorizontalFillDirection.DEFAULT,
121121
) -> None:
122122

123-
self._direction = direction
124-
125123
# Store the "direction" value locally. While they may appear to
126124
# "relate" with the values of the vertical bar, their handling
127125
# is too different to be stored in the same underlying property,
128126
# which could lead to confusion
127+
self._direction = direction
128+
129129
super().__init__(
130130
position,
131131
size,
@@ -138,71 +138,21 @@ def __init__(
138138
(min_value, max_value),
139139
)
140140

141-
# Perform the rendering/drawing of the progress bar using horizontal bar
142-
# specific logic for pixel adjustments.
141+
def _get_sizes_min_max(self) -> Tuple[int, int]:
142+
return 0, self.fill_width()
143143

144-
def _render(
145-
self,
146-
_old_value: Union[int, float],
147-
_new_value: Union[int, float],
148-
_progress_value: float,
149-
) -> None:
150-
"""
151-
Does the work of actually creating the graphical representation of
152-
the value (percentage, aka "progress") to be displayed.
153-
154-
:param _old_value: The previously displayed value
155-
:type _old_value: int/float
156-
:param _new_value: The new value to display
157-
:type _new_value: int/float
158-
:param _progress_value: The value to display, as a percentage, represented
159-
by a float from 0.0 to 1.0 (0% to 100%)
160-
:type _progress_value: float
161-
:rtype: None
162-
"""
163-
164-
_prev_ratio = self.get_value_ratio(_old_value)
165-
_new_ratio = self.get_value_ratio(_new_value)
166-
167-
_old_value_size = int(_prev_ratio * self.fill_width())
168-
_new_value_size = int(_new_ratio * self.fill_width())
169-
170-
# If we have *ANY* value other than "zero" (minimum), we should
171-
# have at least one element showing
172-
if _new_value_size == 0 and _new_value > self.minimum:
173-
_new_value_size = 1
174-
175-
# Conversely, if we have *ANY* value other than 100% (maximum),
176-
# we should NOT show a full bar.
177-
if _new_value_size == self.fill_width() and _new_value < self.maximum:
178-
_new_value_size -= 1
179-
180-
_render_offset = self.margin_size + self.border_thickness
181-
182-
# Default values for increasing value
183-
_color = 2
184-
_incr = 1
185-
_start = max(_old_value_size + _render_offset, _render_offset)
186-
_end = max(_new_value_size, 0) + _render_offset
187-
188-
if _old_value_size >= _new_value_size:
189-
# Override defaults to be decreasing
190-
_color = 0 # Clear
191-
_incr = -1 # Iterate range downward
192-
_start = max(_old_value_size + _render_offset, _render_offset) - 1
193-
_end = max(_new_value_size + _render_offset, _render_offset) - 1
194-
# If we're setting to minimum, make sure we're clearing by
195-
# starting one "bar" higher
196-
if _new_value == self.minimum:
197-
_start += 1
198-
199-
if self._direction == HorizontalFillDirection.RIGHT_TO_LEFT:
200-
_ref_pos = self.widget_width - 1
201-
_end = _ref_pos - _end # Those pesky "off-by-one" issues
202-
_start = _ref_pos - _start
203-
_incr = -1 if _start > _end else 1
204-
_color = 0 if _old_value > _new_value else 2
205-
206-
for hpos in range(_start, _end, _incr):
207-
for vpos in range(_render_offset, _render_offset + self.fill_height()):
208-
self._bitmap[hpos, vpos] = _color
144+
def _get_value_sizes(self, _old_ratio: float, _new_ratio: float) -> Tuple[int, int]:
145+
return int(_old_ratio * self.fill_width()), int(_new_ratio * self.fill_width())
146+
147+
def _get_horizontal_fill(
148+
self, _start: int, _end: int, _incr: int
149+
) -> Tuple[int, int, int]:
150+
return _start, _end, _incr
151+
152+
def _get_vertical_fill(
153+
self, _start: int, _end: int, _incr: int
154+
) -> Tuple[int, int, int]:
155+
return 0, self.fill_height(), 1
156+
157+
def _invert_fill_direction(self) -> bool:
158+
return self._direction == HorizontalFillDirection.RIGHT_TO_LEFT

adafruit_progressbar/verticalprogressbar.py

Lines changed: 19 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -138,74 +138,23 @@ def __init__(
138138
(min_value, max_value),
139139
)
140140

141-
# Perform the rendering/drawing of the progress bar using vertical bar
142-
# specific logic for pixel adjustments. The added complexity is that by
143-
# default, the bar fills from bottom to top, which is a _descending_ value of
144-
# the **Y** axis, versus an ascending value for the default horizontal
145-
# progress bar direction.
141+
def _get_sizes_min_max(self) -> Tuple[int, int]:
142+
return 0, self.fill_height()
146143

147-
def _render(
148-
self,
149-
_old_value: Union[int, float],
150-
_new_value: Union[int, float],
151-
_progress_value: float,
152-
) -> None:
153-
"""
154-
Does the work of actually creating the graphical representation of
155-
the value (percentage, aka "progress") to be displayed.
156-
157-
:param _old_value: The previously displayed value
158-
:type _old_value: int/float
159-
:param _new_value: The new value to display
160-
:type _new_value: int/float
161-
:param _progress_value: The value to display, as a percentage, represented
162-
by a float from 0.0 to 1.0 (0% to 100%)
163-
:type _progress_value: float
164-
:rtype: None
165-
"""
166-
167-
_prev_ratio = self.get_value_ratio(_old_value)
168-
_new_ratio = self.get_value_ratio(_new_value)
169-
170-
_old_value_size = int(_prev_ratio * self.fill_height())
171-
_new_value_size = int(_new_ratio * self.fill_height())
172-
173-
# If we have *ANY* value other than "zero" (minimum), we should
174-
# have at least one element showing
175-
if _new_value_size == 0 and _new_value > self.minimum:
176-
_new_value_size = 1
177-
178-
# Conversely, if we have *ANY* value other than 100% (maximum),
179-
# we should NOT show a full bar.
180-
if _new_value_size == self.fill_height() and _new_value < self.maximum:
181-
_new_value_size -= 1
182-
183-
_render_offset = self.margin_size + self.border_thickness
184-
185-
# Default values for increasing value
186-
_color = 2
187-
_incr = 1
188-
_start = max(_old_value_size + _render_offset, _render_offset)
189-
_end = max(_new_value_size, 0) + _render_offset
190-
191-
if _old_value_size >= _new_value_size:
192-
# Override defaults to be decreasing
193-
_color = 0 # Clear
194-
_incr = -1 # Iterate range downward
195-
_start = max(_old_value_size + _render_offset, _render_offset)
196-
_end = max(_new_value_size + _render_offset, _render_offset) - 1
197-
# If we're setting to minimum, make sure we're clearing by
198-
# starting one "bar" higher
199-
if _new_value == self.minimum:
200-
_start += 1
201-
202-
if self._direction == VerticalFillDirection.BOTTOM_TO_TOP:
203-
_ref_pos = self.widget_height - 1
204-
_end = _ref_pos - _end # Those pesky "off-by-one" issues
205-
_start = _ref_pos - _start
206-
_incr = -1 if _start > _end else 1
207-
_color = 0 if _old_value > _new_value else 2
208-
209-
for vpos in range(_start, _end, _incr):
210-
for hpos in range(_render_offset, _render_offset + self.fill_width()):
211-
self._bitmap[hpos, vpos] = _color
144+
def _get_value_sizes(self, _old_ratio: float, _new_ratio: float) -> Tuple[int, int]:
145+
return int(_old_ratio * self.fill_height()), int(
146+
_new_ratio * self.fill_height()
147+
)
148+
149+
def _get_horizontal_fill(
150+
self, _start: int, _end: int, _incr: int
151+
) -> Tuple[int, int, int]:
152+
return 0, self.fill_width(), 1
153+
154+
def _get_vertical_fill(
155+
self, _start: int, _end: int, _incr: int
156+
) -> Tuple[int, int, int]:
157+
return _start, _end, _incr
158+
159+
def _invert_fill_direction(self) -> bool:
160+
return self._direction == VerticalFillDirection.BOTTOM_TO_TOP

0 commit comments

Comments
 (0)