aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--srb_lib.py2
-rwxr-xr-xsrb_tk.py54
-rwxr-xr-xstackrpms_tk_lib.py13
3 files changed, 42 insertions, 27 deletions
diff --git a/srb_lib.py b/srb_lib.py
index 7acda8b..f7f79a5 100644
--- a/srb_lib.py
+++ b/srb_lib.py
@@ -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.
diff --git a/srb_tk.py b/srb_tk.py
index 88610a3..f78569a 100755
--- a/srb_tk.py
+++ b/srb_tk.py
@@ -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))
bgstack15