icons.py
  1  # SPDX-FileCopyrightText: 2020 Jeff Epler for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  # The MIT License (MIT)
  6  #
  7  # Copyright (c) 2020 Jeff Epler for Adafruit Industries LLC
  8  #
  9  # Permission is hereby granted, free of charge, to any person obtaining a copy
 10  # of this software and associated documentation files (the "Software"), to deal
 11  # in the Software without restriction, including without limitation the rights
 12  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 13  # copies of the Software, and to permit persons to whom the Software is
 14  # furnished to do so, subject to the following conditions:
 15  #
 16  # The above copyright notice and this permission notice shall be included in
 17  # all copies or substantial portions of the Software.
 18  #
 19  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 20  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 21  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 22  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 23  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 24  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 25  # THE SOFTWARE.
 26  """
 27  Icon Bar suitable for navigation by joystick
 28  """
 29  
 30  import adafruit_imageload.bmp
 31  import displayio
 32  
 33  def make_palette(seq):
 34      """Create a palette from a sequence of colors"""
 35      pal = displayio.Palette(len(seq))
 36      for i, color in enumerate(seq):
 37          if color is None:
 38              pal.make_transparent(i)
 39          else:
 40              pal[i] = color
 41      return pal
 42  
 43  BLACK, WHITE, RED, BLUE = 0x111111, 0xffffff, 0xff0000, 0x0000ff
 44  
 45  PALETTE_NORMAL = make_palette([BLACK, WHITE, BLACK, BLACK])
 46  PALETTE_SELECTED = make_palette([BLACK, WHITE, RED, BLACK])
 47  PALETTE_ACTIVE = make_palette([BLACK, WHITE, BLACK, BLUE])
 48  PALETTE_BOTH = make_palette([BLACK, WHITE, RED, BLUE])
 49  PALETTES = [PALETTE_NORMAL, PALETTE_ACTIVE, PALETTE_SELECTED, PALETTE_BOTH]
 50  
 51  class IconBar:
 52      """An icon bar presents n 16x16 icons in a row.
 53  One icon can be "selected" and any number can be "active"."""
 54      def __init__(self, n=8, filename="/rsrc/icons.bmp"):
 55          self.group = displayio.Group()
 56          self.bitmap_file = open(filename, "rb")
 57          self.bitmap = adafruit_imageload.bmp.load(self.bitmap_file, bitmap=displayio.Bitmap)[0]
 58  
 59          self._selected = None
 60          self.icons = [displayio.TileGrid(self.bitmap,
 61                                           pixel_shader=PALETTE_NORMAL, x=16*i,
 62                                           y=0, width=1, height=1,
 63                                           tile_width=16, tile_height=16)
 64                        for i in range(n)]
 65          self.active = [False] * n
 66  
 67          for i, icon in enumerate(self.icons):
 68              icon[0] = i
 69              self.group.append(icon)
 70          self.select(0)
 71  
 72      @property
 73      def selected(self):
 74          """The currently selected icon"""
 75          return self._selected
 76  
 77      @selected.setter
 78      def selected(self, n):
 79          self.select(n)
 80  
 81      def select(self, n):
 82          """Select the n'th icon"""
 83          old_selected = self._selected
 84          self._selected = n
 85          if n != old_selected:
 86              self._refresh(n)
 87              if old_selected is not None:
 88                  self._refresh(old_selected)
 89  
 90      def set_active(self, n, new_state):
 91          """Sets the n'th icon's active state to new_state"""
 92          new_state = bool(new_state)
 93          if self.active[n] == new_state:
 94              return
 95          self.active[n] = new_state
 96          self._refresh(n)
 97  
 98      def activate(self, n):
 99          """Set the n'th icon to be active"""
100          self.set_active(n, True)
101  
102      def deactivate(self, n):
103          """Set the n'th icon to be inactive"""
104          self.set_active(n, False)
105  
106      def toggle(self, n):
107          """Toggle the state of the n'th icon"""
108          self.set_active(n, not self.active[n])
109          print()
110  
111      def _refresh(self, n):
112          """Update the appearance of the n'th icon"""
113          palette_index = self.active[n] + 2 * (self._selected == n)
114          self.icons[n].pixel_shader = PALETTES[palette_index]