Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions calculator/gui/base_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import api
import tkinter as tk
from abc import ABC, abstractmethod

class AbstractBaseWidget(ABC):
def __init__(self, calculator: api.Calculator):
self.parent = None
self.frame = None
self.calculator = calculator
self.prev_window_resolution = (0,0)

def get_window_resolution(self):
return (self.parent.winfo_width(), self.parent.winfo_height())

def init_gui(self, parent):
self.parent = parent
self.frame = tk.Frame(parent)
self.prev_window_resolution = self.get_window_resolution()
self._create_layout(self.prev_window_resolution)

@abstractmethod
def _create_layout(self, window_resolution: tuple):
pass

def _destroy_layout(self):
for child in self.frame.winfo_children():
child.destroy()

@abstractmethod
def _update(self):
pass

def update(self):
window_resolution = self.get_window_resolution()
if self.prev_window_resolution != window_resolution:
self._destroy_layout()
self._create_layout(window_resolution)
self._update()
self.prev_window_resolution = window_resolution
80 changes: 58 additions & 22 deletions calculator/gui/button.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,71 @@
import api
import tkinter as tk
from dataclasses import dataclass, field
from gui.base_widget import AbstractBaseWidget

LAYOUT_STANDARD = ["AC", "CE", "%", "/",
"7", "8", "9", "x",
"4", "5", "6", "-",
"1", "2", "3", "+",
"+/-", "0", ".", "="]
NO_BUTTON = "NO_BUTTON"

@dataclass
class ButtonLayout:
width: int
buttons: list[str]
size_overrides: dict = field(default_factory=dict)

LAYOUT_STANDARD_TALL = ButtonLayout(4,
["AC", "CE", "%", "/",
"7", "8", "9", "x",
"4", "5", "6", "-",
"1", "2", "3", "+",
"+/-", "0", ".", "="])

LAYOUT_STANDARD_WIDE = ButtonLayout(5,
["AC", "7", "8", "9", "/",
"CE", "4", "5", "6", "x",
"%", "1", "2", "3", "-",
"+/-", "0", ".", "=", "+"])

def calc_button(root, calculator: api.Calculator, display_text):
button = tk.Button(root, text=display_text, command=lambda: calculator.input_button(display_text))
return button

class CalculatorButtons:
def __init__(self, calculator: api.Calculator):
self.calculator = calculator
self.frame = None
self.buttons = []
class CalculatorButtons(AbstractBaseWidget):
def __init__(self, calculator):
super().__init__(calculator)
self.prev_column_count = 0

def create_gui(self, root, layout=LAYOUT_STANDARD, width=4):
self.frame = tk.Frame(root)
def _create_layout(self, window_resolution):
aspect_ratio = window_resolution[0] / window_resolution[1]
if aspect_ratio > 1:
self.create_buttons(LAYOUT_STANDARD_WIDE)
self.prev_column_count = LAYOUT_STANDARD_WIDE.width
else:
self.create_buttons(LAYOUT_STANDARD_TALL)
self.prev_column_count = LAYOUT_STANDARD_TALL.width

def _destroy_layout(self):
super()._destroy_layout()
for i in range(self.prev_column_count):
self.frame.columnconfigure(i, weight=0)

def _update(self):
pass

for i, label in enumerate(layout):
def create_buttons(self, layout: ButtonLayout):
for i, label in enumerate(layout.buttons):
if label == NO_BUTTON:
continue
x = i%layout.width
y = int(i/layout.width)
size_x = 1
size_y = 1
if (x,y) in layout.size_overrides:
size_x, size_y = layout.size_overrides[(x,y)]

button = calc_button(self.frame, self.calculator, label)
button.grid(column=i%width, row=int(i/width), sticky=tk.NSEW)
self.buttons.append(button)
button.grid(column=x, row=y, sticky=tk.NSEW, columnspan=size_x, rowspan=size_y)

for i in range(width):
self.frame.grid_columnconfigure(i, uniform="calc_buttons", weight=1)
for i in range(layout.width):
self.frame.grid_columnconfigure(i, weight=1)

for i in range(int(len(layout)/width)):
self.frame.grid_rowconfigure(i, weight=1)

def update(self):
pass
for i in range(int(len(layout.buttons)/layout.width)):
self.frame.grid_rowconfigure(i, weight=1)
13 changes: 6 additions & 7 deletions calculator/gui/display.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import api
import tkinter as tk
from gui.base_widget import AbstractBaseWidget

class CalculatorDisplay:
class CalculatorDisplay(AbstractBaseWidget):
def __init__(self, calculator: api.Calculator):
self.calculator = calculator
self.frame = None
super().__init__(calculator)
self.upper_entry = None
self.lower_entry = None

def create_gui(self, root):
self.frame = tk.Frame(root)
def _create_layout(self, window_resolution):
self.upper_entry = tk.Entry(self.frame, state=tk.DISABLED, justify=tk.RIGHT)
self.lower_entry = tk.Entry(self.frame, state=tk.DISABLED, justify=tk.RIGHT)
self.upper_entry.pack(fill=tk.BOTH,expand=True,side=tk.TOP)
self.lower_entry.pack(fill=tk.BOTH,expand=True,side=tk.BOTTOM)

def update(self):
def _update(self):
self.upper_entry.configure(state=tk.NORMAL)
self.lower_entry.configure(state=tk.NORMAL)

Expand Down
4 changes: 2 additions & 2 deletions calculator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def create_gui(self):
self.display = gui.CalculatorDisplay(self.calculator)
self.buttons = gui.CalculatorButtons(self.calculator)

self.display.create_gui(self.window)
self.buttons.create_gui(self.window)
self.display.init_gui(self.window)
self.buttons.init_gui(self.window)

self.display.frame.pack(fill=tk.BOTH,expand=True,side=tk.TOP,padx=10,pady=(10,0))
self.buttons.frame.pack(fill=tk.BOTH,expand=True,side=tk.BOTTOM,padx=10,pady=(0,10))
Expand Down