diff options
-rw-r--r-- | srb_lib.py | 2 | ||||
-rwxr-xr-x | srb_tk.py | 54 | ||||
-rwxr-xr-x | stackrpms_tk_lib.py | 13 |
3 files changed, 42 insertions, 27 deletions
@@ -28,7 +28,7 @@ # Dependencies: import sys, struct -srb_lib_version = "20240331c" +srb_lib_version = "20240404a" # Table of byte positions of values in the savegame file, minus the first four bytes which are the checksum. Due to zero-indexing of python lists, but for ease of usage, we will always put a zero as the value of index 0. That is, profile 1 will use index 1 of the list. # "Z<dddddddd" is the start of a profile. @@ -90,8 +90,9 @@ class App(tk.Frame): self.master.tk.call("wm","iconphoto",self.master._w,imgicon) # app variables - self.silent = tk.BooleanVar() - self.silent.set(True) + self.silent = tk.BooleanVar(value=True) + self.frame_backgrounds = tk.BooleanVar(value=False) + self.frame_backgrounds.trace("w",self.set_frame_backgrounds) # data variables # Do not use traces for most things, because it will catch itself in a loop. Instead, use the bind <Key-Enter> on the form fields. @@ -160,18 +161,21 @@ class App(tk.Frame): self.statustext = tk.StringVar() # app label, for vanity + self.background_color = self.master.cget("bg") self.lbl_app = tk.Label(self.master,text="Savegame editor for Snoopy vs. the Red Baron") self.lbl_app.grid(row=0,column=0,columnspan=2) stk.Tooltip(self.lbl_app,text="Also checkout the cli with ./srb.py") self.lbl_checksum = tk.Label(self.master,text="Checksum",underline=0) - self.lbl_checksum.grid(row=1,column=0) + self.lbl_checksum.grid(row=1,column=1) self.ent_checksum = tk.Entry(state="readonly",textvariable=self.checksum) #self.ent_checksum.bind("<Key-Return>",self.load_form_into_data) - self.ent_checksum.grid(row=2,column=0) + self.ent_checksum.grid(row=1,column=0) self.chk_silent = tk.Checkbutton(self.master,text="silent",variable=self.silent) - self.chk_silent.grid(row=2,column=1) - self.frm_profiles = tk.Frame(self.master) #,background="orange",borderwidth=1) - self.frm_profiles.grid(row=3,column=0,columnspan=2) + self.chk_silent.grid(row=2,column=0) + self.chk_backgrounds = tk.Checkbutton(self.master,text="frame colors",variable=self.frame_backgrounds) + self.chk_backgrounds.grid(row=3,column=0) + self.frm_profiles = tk.Frame(self.master) + self.frm_profiles.grid(row=4,column=0,columnspan=2) # investigate radio button key-bind, up-down, to increment/decrement choice? tk.Label(self.frm_profiles,text="Used").grid(row=0,column=2) tk.Label(self.frm_profiles,text="Tutorial").grid(row=0,column=3) @@ -211,7 +215,7 @@ class App(tk.Frame): #self.selected_profile.set(1) # purposefully do not set this value. # one profile, so we will have to use the value of self.selected_profile - self.frm_curprof = tk.Frame(self.master) #,background="red") + self.frm_curprof = tk.Frame(self.master) self.frm_curprof.grid(row=5,column=0,rowspan=22,columnspan=2) # most form fields are inside the current profile self.img_money = get_srb_image("money.png",20,16) @@ -293,7 +297,7 @@ class App(tk.Frame): self.chk_pur_plane_baron.grid(row=11,column=1,sticky="W") # level and levelsets - self.frm_levels = tk.Frame(self.master) #,borderwidth=1,background="green") + self.frm_levels = tk.Frame(self.master) self.frm_levels.grid(row=0,column=3,rowspan=len(srb_lib.LEVELS)+4) self.lbl_levelsets = [] self.spn_levelsets = [] @@ -381,6 +385,18 @@ class App(tk.Frame): # and now open the first file self.func_open(self.current_file.get()) + def set_frame_backgrounds(self, arg1 = None, arg2 = None, arg3 = None): + """ Reacts to the frame colors checkbox and sets frames which make development and layout easier. """ + if self.frame_backgrounds.get(): + self.frm_profiles.config(background="orange",borderwidth=1) + self.frm_curprof.config(background="red",borderwidth=1) + self.frm_levels.config(background="green",borderwidth=1) + else: + bg = self.background_color # I manually set this when instantiating App with master.cget("bg") + self.frm_profiles.config(background=bg,borderwidth=0) + self.frm_curprof.config(background=bg,borderwidth=0) + self.frm_levels.config(background=bg,borderwidth=0) + def button_action_level(self, level_obj, action, type_): """ Handle button press from "none" and "all" for balloons and letters for a level """ #print(f"debug (button_action_level): {level_obj}, {action}, {type_}") @@ -416,15 +432,15 @@ class App(tk.Frame): bdata, _ = srb_lib.set_profile_in_use(bdata,3,self.prof3_used.get()) bdata, message = srb_lib.set_name(bdata,1,self.prof1name.get()) if message != "": - self.flash_entry(self.ent_prof1name) + stk.flash_entry(self.ent_prof1name,["red","white","red","white","red","white","red","white"],333) raise Exception("Profile 1 name") bdata, message = srb_lib.set_name(bdata,2,self.prof2name.get()) if message != "": - self.flash_entry(self.ent_prof2name) + stk.flash_entry(self.ent_prof2name,["red","white","red","white","red","white","red","white"],333) raise Exception("Profile 2 name") bdata, message = srb_lib.set_name(bdata,3,self.prof3name.get()) if message != "": - self.flash_entry(self.ent_prof3name) + stk.flash_entry(self.ent_prof3name,["red","white","red","white","red","white","red","white"],333) raise Exception("Profile 3 name") #print(f"debug: loading data with value prof1 tutorial: {self.prof1tut.get()}") bdata, _ = srb_lib.set_tutorial_completed(bdata,1,self.prof1tut.get()) @@ -516,20 +532,6 @@ class App(tk.Frame): self.bchecksum = csum self.load_data_into_form() - def flash_entry(self, this_entry): - """ Flash the offending entry box red for one second. """ - # Improve: move this to stackrpms_tk_lib? - current_color = this_entry.cget("background") - #print(f"DEBUG (flash_entry): this_entry={this_entry}") - #print(f"DEBUG: current_color {current_color}") - if current_color in ["#ffffff","white"]: # name is supposed to work but it does not - next_color = "red" #if current_color == "#ffffff" else "white" - this_entry.config(background=next_color) - self.master.after(1000, lambda te=this_entry: self.flash_entry(te)) - else: - next_color = "white" - this_entry.config(background=next_color) - # functions def func_about(self): """ Display about dialog. """ diff --git a/stackrpms_tk_lib.py b/stackrpms_tk_lib.py index a086344..e106aae 100755 --- a/stackrpms_tk_lib.py +++ b/stackrpms_tk_lib.py @@ -12,6 +12,7 @@ # https://coderslegacy.com/python/create-a-status-bar-in-tkinter/ # https://stackoverflow.com/questions/38329996/enable-mouse-wheel-in-spinbox-tk-python # https://insolor.github.io/effbot-tkinterbook-archive/tkinter-events-and-bindings.htm +# https://stackoverflow.com/questions/27533244/how-to-make-a-flashing-text-box-in-tkinter/78277443#78277443 # Improve: from tkinter import * from tkinter import Spinbox as tkSpinbox, Checkbutton as tkCheckbutton, Entry as tkEntry, Radiobutton as tkRadiobutton @@ -440,3 +441,15 @@ class Radiobutton(tkRadiobutton): if i1 == self.__var.get(): i.focus() break + +def flash_entry(this_entry, colorlist, ms = 1000): + """ + Flash the offending entry box through the colorlist, one color every 'ms' milliseconds. + Example: + flash_entry(entry_that_was_invalid,["red","white"]) + """ + thiscolor = colorlist.pop(0) + this_entry.config(background = thiscolor) + if len(colorlist) > 0: + top = this_entry._nametowidget(this_entry.winfo_parent()) + top.after(ms, lambda te=this_entry, c=colorlist, ms=ms: flash_entry(te,c,ms)) |