commit c33f19b647f174c17a6d27d1e6960e783af85e0b Author: alex Date: Tue Dec 31 09:41:56 2024 +0100 Initial Commit diff --git a/app.py b/app.py new file mode 100644 index 0000000..fc0d46d --- /dev/null +++ b/app.py @@ -0,0 +1,246 @@ +import math +import json +import tkinter as tk +from tkinter import ttk +import customtkinter as ctk + + +class OutputEntry: + def __init__(self, master, count, text): + self.master = master + self.count = count + self.text = text + self.txtvar = ctk.StringVar() + self._create() + self.hide_number(hide_linenumber.get()) + + def _create(self): + self.fr_lo = ctk.CTkFrame(self.master) + self.fr_lo.pack(expand=True, fill='x') + self.lb_ln = ctk.CTkLabel(self.fr_lo, textvariable=self.txtvar, anchor='w') + self.lb_ln.pack(side='left') + self.lb_output = ctk.CTkLabel(self.fr_lo, text=self.text, anchor='w') + self.lb_output.pack(expand=True, fill='x', side='left') + + def hide_number(self, state): + if state: + self.txtvar.set(str(self.count) + ') ') + else: + self.txtvar.set('') + + def hide(self): + self.fr_lo.pack_forget() + + +def write_config(config): + with open('config_abacus.json', 'w') as file: + json.dump(config, file) + + +def load_config(): + try: + with open('config_abacus.json') as file: + return json.load(file) + except FileNotFoundError: + config = { + "resolution": "400x400" + } + write_config(config) + + +config = load_config() + +assert config is not None + + +def on_exit(): + config['resolution'] = app.geometry() + config['linenumber'] = hide_linenumber.get() + config['variable_names'] = None + config['variables'] = variables + write_config(config) + app.destroy() + + +app = ctk.CTk() +app.geometry(config.get('resolution')) +app.title('AbacusNG') +app.grid_columnconfigure((0, 1, 2, 3), weight=1) +app.grid_rowconfigure((0, 1), weight=0) +app.grid_rowconfigure((2), weight=1) +app.protocol("WM_DELETE_WINDOW", on_exit) + + +def round2(x): + return round(x, 2) + + +def round3(x): + return round(x, 3) + + +def gz(x): + return int(x) + + +def show(x): + output = '' + for k, v in variables.items(): + output += k + ': ' + str(v) + '\n' + create_output_entry(output) + + +def clear(): + global output_entries + global count + count = 0 + for oe in output_entries: + oe.hide() + output_entries = list() + input_str.set(str(0)) + return 'Cleared' + + +variables = config.get('variables') +count = 0 + +output_entries = list() + +functions = {'r2': round2, 'r3': round3, 'show': show, 'gz': int} +input_str = ctk.StringVar() +hide_linenumber = ctk.BooleanVar(value=config.get('linenumber')) + + +def hide_numbers(): + for oe in output_entries: + oe.hide_number(hide_linenumber.get()) + + +def create_output_entry(text): + global count + count = count + 1 + output_entries.append(OutputEntry(fr_output, count, text)) + + +def build_chunks(text): + begin = 0 + chunks = list() + j = 0 + for i, c in enumerate(text): + j = i + 1 + if c in ['+', '-', '/', '*', '(', ')', '.']: + chunk = text[begin:i] + chunk = chunk.strip() + if chunk.isalnum(): + chunks.append(chunk) + chunks.append(c) + begin = i + 1 + chunk = text[begin:j] + chunk = chunk.strip() + if chunk.isalnum(): + chunks.append(chunk) + return chunks + + +def get_input(event): + inp = input_str.get() + result = parse_input_new(inp) + create_output_entry(result) + + +def calculate(t): + try: + output = eval(t) + except Exception as e: + output = e + return output + + +def parse_input_new(t: str): + t = t.strip() + t = t.replace('.', '') + t = t.replace(',', '.') + input = t + comment = None + var = None + func = None + + # kommentar + if input[0] == '#': # ganze zeile ist ein kommentar + comment = input[1:] + elif input.find('#') > -1: # nur ein teil ist ein kommentar + input, comment = input.split('#') + input = input.strip() + comment = comment.strip() + + # variablenzuweisung + if input.find('=') > -1: + var, input = input.split('=') + var = var.strip() + input = input.strip() + if input.find(':') > -1: + func, input = input.split(':') + func = func.strip() + input = input.strip() + print('input', input) + + chunks = build_chunks(input) + + for i, c in enumerate(chunks): + v = variables.get(c) + print('v:', v) + if v: + chunks[i] = v + print('chunks after', chunks) + + result = ''.join(chunks) + if len(result) > 0: + result = calculate(result) + if func: + if func == 'show': + if len(str(result)) <= 0: + show(count) + result = str(input) + ' = ' + str(result) + else: + f = functions.get(func) + if f: + result = f(result) + if var: + variables[var] = str(result) + + result = str(result) + result = result.replace('.', ',') + + input_str.set(result) + + # output modifikatoren + + result = input + ' = ' + result + if comment: + result = result + ' # ' + comment + + return result + + +ent_input = ctk.CTkEntry(app, placeholder_text='Enter it', font=('CTkFont', 18), justify='right', + textvariable=input_str) +ent_input.focus() +ent_input.grid(row=0, column=0, pady=(10, 20), columnspan=4, sticky='ew') + +ent_input.bind('', get_input) +ent_input.bind('', get_input) + +checkbox_ln = ctk.CTkCheckBox(app, text="Linenumber", variable=hide_linenumber, command=hide_numbers) +checkbox_ln.grid(row=1, column=0, padx=20, pady=(10, 20), sticky="w") +checkbox_var = ctk.CTkCheckBox(app, text="variables") +checkbox_var.grid(row=1, column=1, padx=20, pady=(10, 20), sticky="w") + +btn_clear = ctk.CTkButton(app, text="clear", command=clear) +btn_clear.grid(row=1, column=2, padx=20, pady=(10, 20), sticky="w") +btn_save = ctk.CTkButton(app, text="save") +btn_save.grid(row=1, column=3, padx=20, pady=(10, 20), sticky="w") + +fr_output = ctk.CTkScrollableFrame(app) +fr_output.grid(row=2, column=0, columnspan=4, sticky='news') + +app.mainloop()