140 lines
4.8 KiB
Python
Executable file
140 lines
4.8 KiB
Python
Executable file
# SPDX-FileCopyrightText: 2019 Melissa LeBlanc-Williams for Adafruit Industries
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""
|
|
CircuitPython library to handle the input and calculations
|
|
|
|
* Author(s): Melissa LeBlanc-Williams
|
|
"""
|
|
|
|
# pylint: disable=eval-used
|
|
def calculate(number_one, operator, number_two):
|
|
result = eval(number_one + operator + number_two)
|
|
if int(result) == result:
|
|
result = int(result)
|
|
return str(result)
|
|
|
|
class Calculator:
|
|
def __init__(self, calc_display, clear_button, label_offset):
|
|
self._error = False
|
|
self._calc_display = calc_display
|
|
self._clear_button = clear_button
|
|
self._label_offset = label_offset
|
|
self._accumulator = "0"
|
|
self._operator = None
|
|
self._equal_pressed = False
|
|
self._operand = None
|
|
self._all_clear()
|
|
|
|
def get_current_operator(self):
|
|
operator = self._operator
|
|
if operator == "*":
|
|
operator = "x"
|
|
return operator
|
|
|
|
def _all_clear(self):
|
|
self._accumulator = "0"
|
|
self._operator = None
|
|
self._equal_pressed = False
|
|
self._clear_entry()
|
|
|
|
def _clear_entry(self):
|
|
self._operand = None
|
|
self._error = False
|
|
self._set_button_ce(False)
|
|
self._set_text("0")
|
|
|
|
def _set_button_ce(self, entry_only):
|
|
self._clear_button.selected = False
|
|
if entry_only:
|
|
self._clear_button.label = "CE"
|
|
else:
|
|
self._clear_button.label = "AC"
|
|
|
|
def _set_text(self, text):
|
|
self._calc_display.text = text
|
|
_, _, screen_w, _ = self._calc_display.bounding_box
|
|
self._calc_display.x = self._label_offset - screen_w
|
|
|
|
def _get_text(self):
|
|
return self._calc_display.text
|
|
|
|
def _handle_number(self, input_key):
|
|
display_text = self._get_text()
|
|
if self._operand is None and self._operator is not None:
|
|
display_text = ""
|
|
elif self._operand is not None and self._operator is not None and self._equal_pressed:
|
|
self._accumulator = self._operand
|
|
self._operator = None
|
|
self._operand = None
|
|
display_text = ""
|
|
elif display_text == "0":
|
|
display_text = ""
|
|
display_text += input_key
|
|
self._set_text(display_text)
|
|
if self._operator is not None:
|
|
self._operand = display_text
|
|
self._set_button_ce(True)
|
|
self._equal_pressed = False
|
|
|
|
def _handle_operator(self, input_key):
|
|
if input_key == "x":
|
|
input_key = "*"
|
|
if self._equal_pressed:
|
|
self._operand = None
|
|
if self._operator is None:
|
|
self._operator = input_key
|
|
else:
|
|
# Perform current calculation before changing input_keys
|
|
if self._operand is not None:
|
|
self._accumulator = calculate(self._accumulator, self._operator, self._operand)
|
|
self._set_text(self._accumulator)
|
|
self._operand = None
|
|
self._operator = input_key
|
|
self._accumulator = self._get_text()
|
|
self._equal_pressed = False
|
|
|
|
def _handle_equal(self):
|
|
if self._operator is not None:
|
|
if self._operand is None:
|
|
self._operand = self._get_text()
|
|
self._accumulator = calculate(self._accumulator, self._operator, self._operand)
|
|
self._set_text(self._accumulator)
|
|
self._equal_pressed = True
|
|
|
|
def _update_operand(self):
|
|
if self._operand is not None:
|
|
self._operand = self._get_text()
|
|
|
|
def add_input(self, input_key):
|
|
try:
|
|
if self._error:
|
|
self._clear_entry()
|
|
elif input_key == "AC":
|
|
self._all_clear()
|
|
elif input_key == "CE":
|
|
self._clear_entry()
|
|
elif self._operator is None and input_key == "0":
|
|
pass
|
|
elif len(input_key) == 1 and 48 <= ord(input_key) <= 57:
|
|
self._handle_number(input_key)
|
|
elif input_key in ('+', '-', '/', 'x'):
|
|
self._handle_operator(input_key)
|
|
elif input_key == ".":
|
|
if not input_key in self._get_text():
|
|
self._set_text(self._get_text() + input_key)
|
|
self._set_button_ce(True)
|
|
self._equal_pressed = False
|
|
elif input_key == "+/-":
|
|
self._set_text(calculate(self._get_text(), "*", "-1"))
|
|
self._update_operand()
|
|
elif input_key == "%":
|
|
self._set_text(calculate(self._get_text(), "/", "100"))
|
|
self._update_operand()
|
|
elif input_key == "=":
|
|
self._handle_equal()
|
|
except (ZeroDivisionError, RuntimeError):
|
|
self._all_clear()
|
|
self._error = True
|
|
self._set_text("Error")
|