icons.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2020 Jeff Epler for Adafruit Industries LLC 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 Icon Bar suitable for navigation by joystick 24 """ 25 26 import adafruit_imageload.bmp 27 import displayio 28 29 def make_palette(seq): 30 """Create a palette from a sequence of colors""" 31 pal = displayio.Palette(len(seq)) 32 for i, color in enumerate(seq): 33 if color is None: 34 pal.make_transparent(i) 35 else: 36 pal[i] = color 37 return pal 38 39 BLACK, WHITE, RED, BLUE = 0x111111, 0xffffff, 0xff0000, 0x0000ff 40 41 PALETTE_NORMAL = make_palette([BLACK, WHITE, BLACK, BLACK]) 42 PALETTE_SELECTED = make_palette([BLACK, WHITE, RED, BLACK]) 43 PALETTE_ACTIVE = make_palette([BLACK, WHITE, BLACK, BLUE]) 44 PALETTE_BOTH = make_palette([BLACK, WHITE, RED, BLUE]) 45 PALETTES = [PALETTE_NORMAL, PALETTE_ACTIVE, PALETTE_SELECTED, PALETTE_BOTH] 46 47 class IconBar: 48 """An icon bar presents n 16x16 icons in a row. 49 One icon can be "selected" and any number can be "active".""" 50 def __init__(self, n=8, filename="/rsrc/icons.bmp"): 51 self.group = displayio.Group(max_size=n) 52 self.bitmap_file = open(filename, "rb") 53 self.bitmap = adafruit_imageload.bmp.load(self.bitmap_file, bitmap=displayio.Bitmap)[0] 54 55 56 self._selected = None 57 self.icons = [displayio.TileGrid(self.bitmap, 58 pixel_shader=PALETTE_NORMAL, x=16*i, 59 y=0, width=1, height=1, 60 tile_width=16, tile_height=16) 61 for i in range(n)] 62 self.active = [False] * n 63 64 for i, icon in enumerate(self.icons): 65 icon[0] = i 66 self.group.append(icon) 67 self.select(0) 68 69 @property 70 def selected(self): 71 """The currently selected icon""" 72 return self._selected 73 74 @selected.setter 75 def selected(self, n): 76 self.select(n) 77 78 def select(self, n): 79 """Select the n'th icon""" 80 old_selected = self._selected 81 self._selected = n 82 if n != old_selected: 83 self._refresh(n) 84 if old_selected is not None: 85 self._refresh(old_selected) 86 87 def set_active(self, n, new_state): 88 """Sets the n'th icon's active state to new_state""" 89 new_state = bool(new_state) 90 if self.active[n] == new_state: 91 return 92 self.active[n] = new_state 93 self._refresh(n) 94 95 def activate(self, n): 96 """Set the n'th icon to be active""" 97 self.set_active(n, True) 98 99 def deactivate(self, n): 100 """Set the n'th icon to be inactive""" 101 self.set_active(n, False) 102 103 def toggle(self, n): 104 """Toggle the state of the n'th icon""" 105 self.set_active(n, not self.active[n]) 106 print() 107 108 def _refresh(self, n): 109 """Update the appearance of the n'th icon""" 110 palette_index = self.active[n] + 2 * (self._selected == n) 111 self.icons[n].pixel_shader = PALETTES[palette_index]