/ src / icons.py
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]