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()