/ adafruit_progressbar.py
adafruit_progressbar.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2020 Brent Rubell for Adafruit Industries 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_progressbar` 24 ================================================================================ 25 26 Dynamic progress bar widget for CircuitPython displays 27 28 29 * Author(s): Brent Rubell 30 31 Implementation Notes 32 -------------------- 33 34 **Software and Dependencies:** 35 36 * Adafruit CircuitPython firmware for the supported boards: 37 https://github.com/adafruit/circuitpython/releases 38 39 """ 40 41 # imports 42 import displayio 43 44 __version__ = "0.0.0-auto.0" 45 __repo__ = "https://github.com/brentru/Adafruit_CircuitPython_ProgressBar.git" 46 47 # pylint: disable=too-many-arguments, too-few-public-methods 48 class ProgressBar(displayio.TileGrid): 49 """A dynamic progress bar widget. 50 51 :param int x: The x-position of the top left corner. 52 :param int y: The y-position of the top left corner. 53 :param int width: The width of the progress bar. 54 :param int height: The height of the progress bar. 55 :param float progress: The percentage of the progress bar. 56 :param bar_color: The color of the progress bar. Can be a hex 57 value for color. 58 :param int outline_color: The outline of the progress bar. Can be a hex 59 value for color. 60 :param int stroke: Used for the outline_color 61 62 """ 63 64 # pylint: disable=invalid-name 65 def __init__( 66 self, 67 x, 68 y, 69 width, 70 height, 71 progress=0.0, 72 bar_color=0x00FF00, 73 outline_color=0xFFFFFF, 74 stroke=1, 75 ): 76 assert isinstance(progress, float), "Progress must be a floating point value." 77 self._bitmap = displayio.Bitmap(width, height, 3) 78 self._palette = displayio.Palette(3) 79 self._palette[0] = 0x0 80 self._palette[1] = outline_color 81 self._palette[2] = bar_color 82 83 self._width = width 84 self._height = height 85 86 self._progress_val = 0.0 87 self.progress = self._progress_val 88 self.progress = progress 89 90 # draw outline rectangle 91 for _w in range(width): 92 for line in range(stroke): 93 self._bitmap[_w, line] = 1 94 self._bitmap[_w, height - 1 - line] = 1 95 for _h in range(height): 96 for line in range(stroke): 97 self._bitmap[line, _h] = 1 98 self._bitmap[width - 1 - line, _h] = 1 99 super().__init__(self._bitmap, pixel_shader=self._palette, x=x, y=y) 100 101 @property 102 def progress(self): 103 """The percentage of the progress bar expressed as a 104 floating point number. 105 106 """ 107 return self._progress_val 108 109 @progress.setter 110 def progress(self, value): 111 """Draws the progress bar 112 113 :param float value: Progress bar value. 114 """ 115 assert value <= 1.0, "Progress value may not be > 100%" 116 assert isinstance( 117 value, float 118 ), "Progress value must be a floating point value." 119 if self._progress_val > value: 120 # uncolorize range from width*value+margin to width-margin 121 # from right to left 122 _prev_pixel = max(2, int(self._width * self._progress_val - 2)) 123 _new_pixel = max(int(self._width * value - 2), 2) 124 for _w in range(_prev_pixel, _new_pixel - 1, -1): 125 for _h in range(2, self._height - 2): 126 self._bitmap[_w, _h] = 0 127 else: 128 # fill from the previous x pixel to the new x pixel 129 _prev_pixel = max(2, int(self._width * self._progress_val - 3)) 130 _new_pixel = min(int(self._width * value - 2), int(self._width * 1.0 - 3)) 131 for _w in range(_prev_pixel, _new_pixel + 1): 132 for _h in range(2, self._height - 2): 133 self._bitmap[_w, _h] = 2 134 self._progress_val = value 135 136 @property 137 def fill(self): 138 """The fill of the progress bar. Can be a hex value for a color or ``None`` for 139 transparent. 140 141 """ 142 return self._palette[0] 143 144 @fill.setter 145 def fill(self, color): 146 """Sets the fill of the progress bar. Can be a hex value for a color or ``None`` for 147 transparent. 148 149 """ 150 if color is None: 151 self._palette[2] = 0 152 self._palette.make_transparent(0) 153 else: 154 self._palette[2] = color 155 self._palette.make_opaque(0)