/ PyPortal_Calculator / titano_code.py
titano_code.py
  1  # SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  """
  6  PyPortal Titano Calculator Demo
  7  """
  8  import time
  9  from collections import namedtuple
 10  import board
 11  import displayio
 12  from adafruit_display_text.label import Label
 13  from adafruit_bitmap_font import bitmap_font
 14  from adafruit_display_shapes.rect import Rect
 15  from adafruit_button import Button
 16  from calculator import Calculator
 17  import adafruit_touchscreen
 18  Coords = namedtuple("Point", "x y")
 19  
 20  # Settings
 21  SCREEN_WIDTH = board.DISPLAY.width
 22  SCREEN_HEIGHT = board.DISPLAY.height
 23  BUTTON_WIDTH = int(SCREEN_WIDTH / 5) # was 60
 24  BUTTON_HEIGHT = int(SCREEN_WIDTH / 10) # was 30
 25  BUTTON_MARGIN = 8
 26  MAX_DIGITS = 29
 27  BLACK = 0x0
 28  ORANGE = 0xFF8800
 29  BLUE = 0x0088FF
 30  WHITE = 0xFFFFFF
 31  GRAY = 0x666666
 32  LABEL_OFFSET = int(SCREEN_WIDTH - (SCREEN_WIDTH/7))
 33  
 34  ts = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
 35                                        board.TOUCH_YD, board.TOUCH_YU,
 36                                        calibration=((5200, 59000), (5800, 57000)),
 37                                        size=(SCREEN_WIDTH, SCREEN_HEIGHT))
 38  
 39  # Make the display context
 40  calc_group = displayio.Group()
 41  board.DISPLAY.show(calc_group)
 42  
 43  # Make a background color fill
 44  color_bitmap = displayio.Bitmap(SCREEN_WIDTH, SCREEN_HEIGHT, 1)
 45  color_palette = displayio.Palette(1)
 46  color_palette[0] = GRAY
 47  bg_sprite = displayio.TileGrid(color_bitmap,
 48                                 pixel_shader=color_palette,
 49                                 x=0, y=0)
 50  calc_group.append(bg_sprite)
 51  
 52  # Load the font
 53  if SCREEN_WIDTH < 480:
 54      font = bitmap_font.load_font("/fonts/Arial-12.bdf")
 55  else:
 56      font = bitmap_font.load_font("/fonts/Arial-Bold-24.bdf")
 57  
 58  buttons = []
 59  
 60  # Some button functions
 61  def button_grid(row, col):
 62      return Coords(BUTTON_MARGIN * (row + 1) + BUTTON_WIDTH * row + 20,
 63                    BUTTON_MARGIN * (col + 1) + BUTTON_HEIGHT * col + 40)
 64  
 65  def add_button(row, col, label, width=1, color=WHITE, text_color=BLACK):
 66      pos = button_grid(row, col)
 67      new_button = Button(x=pos.x, y=pos.y,
 68                          width=BUTTON_WIDTH * width + BUTTON_MARGIN * (width - 1),
 69                          height=BUTTON_HEIGHT, label=label, label_font=font,
 70                          label_color=text_color, fill_color=color, style=Button.ROUNDRECT)
 71      buttons.append(new_button)
 72      return new_button
 73  
 74  def find_button(label):
 75      result = None
 76      for _, btn in enumerate(buttons):
 77          if btn.label == label:
 78              result = btn
 79      return result
 80  
 81  border = Rect(int(SCREEN_WIDTH/18), 8, (LABEL_OFFSET), 35, fill=WHITE, outline=BLACK, stroke=2)
 82  calc_display = Label(font, text="0", color=BLACK)
 83  calc_display.y = 25
 84  
 85  clear_button = add_button(0, 0, "AC")
 86  add_button(1, 0, "+/-")
 87  add_button(2, 0, "%")
 88  add_button(3, 0, "/", 1, ORANGE, WHITE)
 89  add_button(0, 1, "7")
 90  add_button(1, 1, "8")
 91  add_button(2, 1, "9")
 92  add_button(3, 1, "x", 1, ORANGE, WHITE)
 93  add_button(0, 2, "4")
 94  add_button(1, 2, "5")
 95  add_button(2, 2, "6")
 96  add_button(3, 2, "-", 1, ORANGE, WHITE)
 97  add_button(0, 3, "1")
 98  add_button(1, 3, "2")
 99  add_button(2, 3, "3")
100  add_button(3, 3, "+", 1, ORANGE, WHITE)
101  add_button(0, 4, "0", 2)
102  add_button(2, 4, ".")
103  add_button(3, 4, "=", 1, BLUE, WHITE)
104  
105  # Add the display and buttons to the main calc group
106  calc_group.append(border)
107  calc_group.append(calc_display)
108  for b in buttons:
109      calc_group.append(b)
110  
111  calculator = Calculator(calc_display, clear_button, LABEL_OFFSET)
112  
113  button = ""
114  while True:
115      point = ts.touch_point
116      if point is not None:
117          # Button Down Events
118          for _, b in enumerate(buttons):
119              if b.contains(point) and button == "":
120                  b.selected = True
121                  button = b.label
122      elif button != "":
123          # Button Up Events
124          last_op = calculator.get_current_operator()
125          op_button = find_button(last_op)
126          # Deselect the last operation when certain buttons are pressed
127          if op_button is not None:
128              if button in ('=', 'AC', 'CE'):
129                  op_button.selected = False
130              elif button in ('+', '-', 'x', '/') and button != last_op:
131                  op_button.selected = False
132          calculator.add_input(button)
133          b = find_button(button)
134          if b is not None:
135              if button not in ('+', '-', 'x', '/') or button != calculator.get_current_operator():
136                  b.selected = False
137          button = ""
138      time.sleep(0.05)