Spacetraders/ui.py
2025-10-15 20:23:50 -04:00

129 lines
4.2 KiB
Python

import tkinter as Tk
from tkinter import ttk as Ttk
from tkinter import font
from pprint import pformat
import threading
from storage import readSave, save
class FieldLabel():
"""
Label to set alongside a text box.
"""
def __init__(self, parent, text, rowNum):
self.widget = Ttk.Label(parent, text=text)
self.widget.grid(row=rowNum, column=1, sticky='e')
class EntryBox():
"""
Basic entry box class.
"""
def __init__(self, parent, textVar=None):
if textVar is None:
self.textVar = Tk.StringVar()
else:
self.textVar = textVar
self.widget = Ttk.Entry(parent, width=12, textvariable=self.textVar)
class SavedEntryBox(EntryBox):
"""
Entry box that saves values to file with a given field name. Reads from that field on launch.
"""
def __init__(self, parent, fieldName, textVar, saveOnEnter=True, saveOnChange=False):
self.textVar = textVar
super().__init__(parent, self.textVar)
self.fieldName = fieldName
value = readSave(fieldName)[fieldName]
if value is not None:
self.textVar.set(value)
else:
self.textVar.set(fieldName)
if saveOnEnter:
self.widget.bind("<Return>", self.saveValue)
if saveOnChange:
self.textVar.trace_add("write", self.saveValue)
def saveValue(self, *args):
save({self.fieldName: self.textVar.get()})
class Container():
def __init__(self, parent, freezeCols=0):
self.widget = Ttk.Frame(parent, padding=(3))
self.freezeCols = freezeCols
def finalize(self):
cols, rows = self.widget.grid_size()
if self.freezeCols > 0:
for i in range(self.freezeCols):
self.widget.grid_columnconfigure(i, weight=0)
for i in range(self.freezeCols, cols):
self.widget.grid_columnconfigure(i, weight=1, uniform='column')
for i in range(rows):
self.widget.grid_rowconfigure(i, weight=0)
class RequesterFrame(Container):
"""
Top-level frame for classes of manipulations.
"""
def __init__(self, parent, label):
super().__init__(parent)
self.widget.configure(height=480, width=330, borderwidth=3, relief="raised")
self.widget.bind('<Enter>', lambda e: self.widget.configure(relief="sunken"))
self.widget.bind('<Leave>', lambda e: self.widget.configure(relief="raised"))
self.label = Ttk.Label(self.widget, text=label, font=font.nametofont('TkHeadingFont'))
self.label.grid(row=0, column=0, sticky='nw')
def finalize(self):
cols, rows = self.widget.grid_size()
self.widget.grid_columnconfigure(0, weight=0)
self.widget.grid_columnconfigure(1, weight=0)
self.widget.grid_columnconfigure(2, weight=1, minsize=150)
for i in range(rows):
self.widget.grid_rowconfigure(i, weight=1, minsize=5)
class ApiButton():
"""
Button which triggers an API call when clicked.
"""
def __init__(self, parent, label, rowNum, apiFunc, args):
self.call = apiFunc
self.args = args
self.row = rowNum
self.parent = parent
self.widget = Ttk.Button(parent, command=self.pressed, text=label)
self.widget.grid(row=rowNum, column=1, columnspan=2, sticky='nsew')
def pressed(self, *args):
progbar = Ttk.Progressbar(self.parent, orient='horizontal', mode='indeterminate', length=10)
progbar.grid(row=self.row, column=0)
threading.Thread(target=self.thread, args=(progbar,)).start()
def thread(self, progbar):
toPass = []
if isinstance(self.args, (list, tuple)):
for arg in self.args:
if type(arg) is Tk.StringVar:
toPass.append(arg.get())
else:
toPass.append(arg)
else:
if type(self.args) is Tk.StringVar:
toPass.append(self.args.get())
else:
toPass.append(self.args)
self.resCode, self.resData = self.call(toPass)
progbar.grid_forget()
def formatResponse(resCode, resData):
return f"""Response {resCode}:
{pformat(resData)}"""