From 22aff09415f38ad27f60a09ef18cc37994ea71ad Mon Sep 17 00:00:00 2001 From: duncte123 Date: Thu, 27 Aug 2020 09:35:49 +0200 Subject: [PATCH 1/2] WIP adding custom active color --- lp_colors.py | 28 ++++++++++---- window.py | 107 +++++++++++++++++++++++++++++---------------------- 2 files changed, 82 insertions(+), 53 deletions(-) diff --git a/lp_colors.py b/lp_colors.py index 9f7ec9e..73e405f 100644 --- a/lp_colors.py +++ b/lp_colors.py @@ -1,4 +1,5 @@ -curr_colors = [[[0,0,0] for y in range(9)] for x in range(9)] +curr_colors = [[[0, 0, 0] for y in range(9)] for x in range(9)] +# color modes are solid, flash and pulse color_modes = [["solid" for y in range(9)] for x in range(9)] import lp_events, scripts, window @@ -6,10 +7,12 @@ lp_object = None + def init(lp_object_in): global lp_object lp_object = lp_object_in + def code_to_RGB(code): # Used to convert old layouts to the new format only RGB = {0: "#000", @@ -49,10 +52,11 @@ def code_to_RGB(code): rgb.append(int(val + val, 16)) return rgb + def RGB_to_RG(rgb): if rgb[2] != 0: color = list(colorsys.rgb_to_hsv(rgb[0], rgb[1], rgb[2])) - color[0] = color[0] * (106/330) + color[0] = color[0] * (106 / 330) color = list(colorsys.hsv_to_rgb(color[0], color[1], color[2])) color = [round(x) for x in color] for x in range(2): @@ -61,12 +65,15 @@ def RGB_to_RG(rgb): else: return rgb + def setXY(x, y, color): curr_colors[x][y] = color + def getXY(x, y): return curr_colors[x][y] + def list_RGB_to_string(color): color_texts = [hex(c)[2:] for c in color] color_string = "#" @@ -76,13 +83,16 @@ def list_RGB_to_string(color): color_string += c return color_string + def getXY_RGB(x, y): color = getXY(x, y) color_string = list_RGB_to_string(color) return color_string + def luminance(r, g, b): - return ((0.299 * r) + (0.587 * g) + (0.114 * b)) / 255.0 + return ((0.299 * r) + (0.587 * g) + (0.114 * b)) / 255.0 + def updateXY(x, y): if window.lp_connected: @@ -94,7 +104,7 @@ def updateXY(x, y): is_func_key = ((y == 0) or (x == 8)) - #print("Update colors for (" + str(x) + ", " + str(y) + "), is_running = " + str(is_running)) + # print("Update colors for (" + str(x) + ", " + str(y) + "), is_running = " + str(is_running)) if is_running: set_color = scripts.COLOR_PRIMED @@ -112,12 +122,12 @@ def updateXY(x, y): if window.lp_mode == "Mk1": if type(set_color) is int: set_color = code_to_RGB(set_color) - lp_object.LedCtrlXY(x, y, set_color[0]//64, set_color[1]//64) + lp_object.LedCtrlXY(x, y, set_color[0] // 64, set_color[1] // 64) else: if (color_modes[x][y] == "solid") or is_func_key: - #pulse and flash only work on main grid + # pulse and flash only work on main grid if type(set_color) is list: - lp_object.LedCtrlXYByRGB(x, y, [c//4 for c in set_color]) + lp_object.LedCtrlXYByRGB(x, y, [c // 4 for c in set_color]) else: lp_object.LedCtrlXYByCode(x, y, set_color) elif color_modes[x][y] == "pulse": @@ -127,12 +137,13 @@ def updateXY(x, y): lp_object.LedCtrlFlashXYByCode(x, y, set_color) else: if type(set_color) is list: - lp_object.LedCtrlXYByRGB(x, y, [c//4 for c in set_color]) + lp_object.LedCtrlXYByRGB(x, y, [c // 4 for c in set_color]) else: lp_object.LedCtrlXYByCode(x, y, set_color) else: print("[lp_colors] (" + str(x) + ", " + str(y) + ") Launchpad is disconnected, cannot update.") + def update_all(): if window.lp_connected: for x in range(9): @@ -141,6 +152,7 @@ def update_all(): else: print("[lp_colors] Launchpad is disconnected, cannot update.") + def raw_clear(): for x in range(9): for y in range(9): diff --git a/window.py b/window.py index 990dea1..3208a40 100644 --- a/window.py +++ b/window.py @@ -15,6 +15,7 @@ STAT_INACTIVE_COLOR = "#444" SELECT_COLOR = "#f00" DEFAULT_COLOR = [0, 0, 255] +DEFAULT_ACTIVE_COLOR = [255, 0, 0] MK1_DEFAULT_COLOR = [0, 255, 0] INDICATOR_BPM = 480 BUTTON_FONT = ("helvetica", 11, "bold") @@ -47,6 +48,7 @@ lp_connected = False lp_mode = None colors_to_set = [[DEFAULT_COLOR for y in range(9)] for x in range(9)] +active_colors_to_set = [[DEFAULT_ACTIVE_COLOR for y in range(9)] for x in range(9)] def init(lp_object_in, launchpad_in, path_in, prog_path_in, user_path_in, version_in, platform_in): @@ -154,7 +156,7 @@ def connect_dummy(self): global lp_mode global lp_object - lp_connected = True + lp_connected = False lp_mode = "Dummy" self.draw_canvas() self.enable_menu("Layout") @@ -180,6 +182,7 @@ def connect_lp(self): then click 'Redetect Now'.""", [["Ignore", None], ["Redetect Now", self.redetect_lp]] ) + self.connect_dummy() return if lpcon.connect(lp): @@ -209,20 +212,22 @@ def connect_lp(self): def disconnect_lp(self): global lp_connected - try: - scripts.unbind_all() - lp_events.timer.cancel() - lpcon.disconnect(lp_object) - except: - self.redetect_lp() - lp_connected = False - self.clear_canvas() + if lp_connected: + try: + scripts.unbind_all() + lp_events.timer.cancel() + lpcon.disconnect(lp_object) + except: + self.redetect_lp() + lp_connected = False - self.disable_menu("Layout") + self.clear_canvas() - self.stat["text"] = "No Launchpad Connected" - self.stat["bg"] = STAT_INACTIVE_COLOR + self.disable_menu("Layout") + + self.stat["text"] = "No Launchpad Connected" + self.stat["bg"] = STAT_INACTIVE_COLOR def redetect_lp(self): global restart @@ -239,17 +244,17 @@ def unbind_lp(self, prompt_save=True): def load_layout(self): self.modified_layout_save_prompt() name = tk.filedialog.askopenfilename(parent=app, - initialdir=files.LAYOUT_PATH, - title="Load layout", - filetypes=load_layout_filetypes) + initialdir=files.LAYOUT_PATH, + title="Load layout", + filetypes=load_layout_filetypes) if name: files.load_layout_to_lp(name) def save_layout_as(self): name = tk.filedialog.asksaveasfilename(parent=app, - initialdir=files.LAYOUT_PATH, - title="Save layout as...", - filetypes=save_layout_filetypes) + initialdir=files.LAYOUT_PATH, + title="Save layout as...", + filetypes=save_layout_filetypes) if name: if files.LAYOUT_EXT not in name: name += files.LAYOUT_EXT @@ -257,7 +262,7 @@ def save_layout_as(self): files.load_layout_to_lp(name) def save_layout(self): - if files.curr_layout == None: + if files.curr_layout is None: self.save_layout_as() else: files.save_lp_to_layout(files.curr_layout) @@ -265,14 +270,13 @@ def save_layout(self): def click(self, event): gap = int(BUTTON_SIZE // 4) - - + column = min(8, int(event.x // (BUTTON_SIZE + gap))) row = min(8, int(event.y // (BUTTON_SIZE + gap))) if self.grid_drawn: if(column, row) == (8, 0): - #mode change + # mode change self.last_clicked = None if self.button_mode == "edit": self.button_mode = "move" @@ -290,7 +294,7 @@ def click(self, event): self.script_entry_window(column, row) self.last_clicked = None else: - if self.last_clicked == None: + if self.last_clicked is None: self.last_clicked = (column, row) else: move_func = partial(scripts.move, self.last_clicked[0], self.last_clicked[1], column, row) @@ -327,8 +331,8 @@ def draw_button(self, column, row, color="#000000", shape="square"): return self.c.create_oval(x_start + shrink, y_start + shrink, x_end - shrink, y_end - shrink, fill=color, outline="") def draw_canvas(self): - if self.last_clicked != None: - if self.outline_box == None: + if self.last_clicked is not None: + if self.outline_box is None: gap = int(BUTTON_SIZE // 4) x_start = round((BUTTON_SIZE * self.last_clicked[0]) + (gap * self.last_clicked[0])) @@ -342,7 +346,7 @@ def draw_canvas(self): self.outline_box = self.c.create_rectangle(x_start, y_start, x_end, y_end, fill=SELECT_COLOR, outline="") self.c.tag_lower(self.outline_box) else: - if self.outline_box != None: + if self.outline_box is not None: self.c.delete(self.outline_box) self.outline_box = None @@ -395,7 +399,7 @@ def script_entry_window(self, x, y, text_override=None, color_override=None): if MAIN_ICON != None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": dummy = None - #w.call('wm', 'iconphoto', w._w, tk.PhotoImage(file=MAIN_ICON)) + # w.call('wm', 'iconphoto', w._w, tk.PhotoImage(file=MAIN_ICON)) else: w.iconbitmap(MAIN_ICON) @@ -406,7 +410,7 @@ def validate_func(): try: script_validate = scripts.validate_script(text_string) except: - #self.save_script(w, x, y, text_string) # This will fail and throw a popup error + # self.save_script(w, x, y, text_string) # This will fail and throw a popup error self.popup(w, "Script Validation Error", self.error_image, "Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.", "OK") raise if script_validate != True and files.in_error: @@ -423,7 +427,7 @@ def validate_func(): t = tk.scrolledtext.ScrolledText(w) t.grid(column=0, row=0, rowspan=3, padx=10, pady=10) - if text_override == None: + if text_override is None: t.insert(tk.INSERT, scripts.text[x][y]) else: t.insert(tk.INSERT, text_override) @@ -436,8 +440,8 @@ def validate_func(): e_m_Script.add_command(label="Export script", command=export_script_func) e_m.add_cascade(label="Script", menu=e_m_Script) - if color_override == None: - colors_to_set[x][y] = lp_colors.getXY(x, y) + if color_override is None: + colors_to_set[x][y] = lp_colors.getXY(x, y) else: colors_to_set[x][y] = color_override @@ -445,6 +449,7 @@ def validate_func(): colors_to_set[x][y] = lp_colors.code_to_RGB(colors_to_set[x][y]) if all(c < 4 for c in colors_to_set[x][y]): + active_colors_to_set[x][y] = DEFAULT_ACTIVE_COLOR if lp_mode == "Mk1": colors_to_set[x][y] = MK1_DEFAULT_COLOR else: @@ -452,20 +457,29 @@ def validate_func(): ask_color_func = lambda: self.ask_color(w, color_button, x, y, colors_to_set[x][y]) color_button = tk.Button(w, text="Select Color", command=ask_color_func) - color_button.grid(column=1, row=0, padx=(0, 10), pady=(10, 50), sticky="nesw") + color_button.grid(column=1, row=0, padx=(0, 5), pady=(5, 25), sticky="nesw") color_button.config(font=BUTTON_FONT) start_color_str = lp_colors.list_RGB_to_string(colors_to_set[x][y]) self.button_color_with_text_update(color_button, start_color_str) + active_color_button = tk.Button( + w, + text="Select Active Color", + command=lambda: self.ask_color(w, active_color_button, x, y, active_colors_to_set[x][y])) + active_color_button.grid(column=1, row=1, padx=(0, 5), pady=(5, 25), sticky="nesw") + active_color_button.config(font=BUTTON_FONT) + active_color_str = lp_colors.list_RGB_to_string(active_colors_to_set[x][y]) + self.button_color_with_text_update(active_color_button, active_color_str) + save_script_func = lambda: self.save_script(w, x, y, t.get(1.0, tk.END)) save_button = tk.Button(w, text="Bind Button (" + str(x) + ", " + str(y) + ")", command=save_script_func) - save_button.grid(column=1, row=1, padx=(0,10), sticky="nesw") + save_button.grid(column=1, row=2, padx=(0, 10), sticky="nesw") save_button.config(font=BUTTON_FONT) save_button.config(bg="#c3d9C3") unbind_func = lambda: self.unbind_destroy(x, y, w) unbind_button = tk.Button(w, text="Unbind Button (" + str(x) + ", " + str(y) + ")", command=unbind_func) - unbind_button.grid(column=1, row=2, padx=(0,10), pady=10, sticky="nesw") + unbind_button.grid(column=1, row=3, padx=(0, 10), pady=10, sticky="nesw") unbind_button.config(font=BUTTON_FONT) unbind_button.config(bg="#d9c3c3") @@ -478,10 +492,10 @@ def classic_askcolor(self, color=(255, 0, 0), title="Color Chooser"): w = tk.Toplevel(self) w.winfo_toplevel().title(title) w.resizable(False, False) - if MAIN_ICON != None: + if MAIN_ICON is not None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": dummy = None - #w.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) + # w.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) else: w.iconbitmap(MAIN_ICON) @@ -534,7 +548,8 @@ def make_color_button(button_color, column, row, size=100): return color, hex else: return None, None - + + # TODO: figure out a way to make sure that we return the color instead of setting it in here def ask_color(self, window, button, x, y, default_color): global colors_to_set @@ -542,14 +557,15 @@ def ask_color(self, window, button, x, y, default_color): color = self.classic_askcolor(color=tuple(default_color), title="Select Color for Button (" + str(x) + ", " + str(y) + ")") else: color = tkcolorpicker.askcolor(color=tuple(default_color), parent=window, title="Select Color for Button (" + str(x) + ", " + str(y) + ")") - if color[0] != None: + if color[0] is not None: color_to_set = [int(min(255, max(0, c))) for c in color[0]] if all(c < 4 for c in color_to_set): rerun = lambda: self.ask_color(window, button, x, y, default_color) self.popup(window, "Invalid Color", self.warning_image, "That color is too dark to see.", "OK", rerun) else: - colors_to_set[x][y] = color_to_set + # colors_to_set[x][y] = color_to_set self.button_color_with_text_update(button, color[1]) + return color_to_set def button_color_with_text_update(self, button, color): button.configure(bg=color, activebackground=color) @@ -635,7 +651,7 @@ def export_script(self, textbox, window): def popup(self, window, title, image, text, button_text, end_command=None): popup = tk.Toplevel(window) popup.resizable(False, False) - if MAIN_ICON != None: + if MAIN_ICON is not None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": dummy = None #popup.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) @@ -646,7 +662,7 @@ def popup(self, window, title, image, text, button_text, end_command=None): def run_end(): popup.destroy() - if end_command != None: + if end_command is not None: end_command() picture_label = tk.Label(popup, image=image) @@ -661,10 +677,10 @@ def run_end(): def popup_choice(self, window, title, image, text, choices): popup = tk.Toplevel(window) popup.resizable(False, False) - if MAIN_ICON != None: + if MAIN_ICON is not None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": dummy = None - #popup.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) + # popup.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) else: popup.iconbitmap(MAIN_ICON) popup.wm_title(title) @@ -672,7 +688,7 @@ def popup_choice(self, window, title, image, text, choices): def run_end(func): popup.destroy() - if func != None: + if func is not None: func() picture_label = tk.Label(popup, image=image) @@ -698,6 +714,7 @@ def modified_layout_save_prompt(self): if not layout_empty: self.popup_choice(self, "Save Changes?", self.warning_image, "You have made changes to this layout.\nWould you like to save this layout before exiting?", [["Save", self.save_layout], ["Save As...", self.save_layout_as], ["Discard", None]]) + def make(): global root global app @@ -707,7 +724,7 @@ def make(): root_destroyed = False root.protocol("WM_DELETE_WINDOW", close) root.resizable(False, False) - if MAIN_ICON != None: + if MAIN_ICON is not None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": root.call('wm', 'iconphoto', root._w, tk.PhotoImage(file=MAIN_ICON)) else: From 045e2f601b242398a0e7f29b68f58e19a833f91e Mon Sep 17 00:00:00 2001 From: duncte123 Date: Thu, 27 Aug 2020 09:42:17 +0200 Subject: [PATCH 2/2] Reformat to make it look a bit more redable --- window.py | 175 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 75 deletions(-) diff --git a/window.py b/window.py index 3208a40..2785bec 100644 --- a/window.py +++ b/window.py @@ -38,7 +38,6 @@ restart = False lp_object = None - load_layout_filetypes = [('LPHK layout files', [files.LAYOUT_EXT, files.LEGACY_LAYOUT_EXT])] load_script_filetypes = [('LPHK script files', [files.SCRIPT_EXT, files.LEGACY_SCRIPT_EXT])] @@ -67,7 +66,7 @@ def init(lp_object_in, launchpad_in, path_in, prog_path_in, user_path_in, versio USER_PATH = user_path_in VERSION = version_in PLATFORM = platform_in - + if PLATFORM == "windows": MAIN_ICON = os.path.join(PATH, "resources", "LPHK.ico") else: @@ -81,7 +80,7 @@ def __init__(self, master=None): tk.Frame.__init__(self, master) self.master = master self.init_window() - + self.about_image = ImageTk.PhotoImage(Image.open(PATH + "/resources/LPHK-banner.png")) self.info_image = ImageTk.PhotoImage(Image.open(PATH + "/resources/info.png")) self.warning_image = ImageTk.PhotoImage(Image.open(PATH + "/resources/warning.png")) @@ -96,7 +95,7 @@ def __init__(self, master=None): def init_window(self): global root - + self.master.title("LPHK - Novation Launchpad Macro Scripting System") self.pack(fill="both", expand=1) @@ -115,7 +114,7 @@ def init_window(self): self.m.add_cascade(label="Layout", menu=self.m_Layout) self.disable_menu("Layout") - + self.m_Help = tk.Menu(self.m, tearoff=False) open_readme = lambda: webbrowser.open("https://github.com/nimaid/LPHK#lphk-launchpad-hotkey") self.m_Help.add_command(label="Open README...", command=open_readme) @@ -125,7 +124,9 @@ def init_window(self): self.m_Help.add_command(label="User Folder...", command=open_user_folder) open_prog_folder = lambda: files.open_file_folder(PROG_PATH) self.m_Help.add_command(label="Program Folder...", command=open_prog_folder) - display_info = lambda: self.popup(self, "About LPHK", self.about_image, "A Novation Launchpad Macro Scripting System\nMade by Ella Jameson (nimaid)\n\nVersion: " + VERSION + "\nFile format version: " + files.FILE_VERSION, "Done") + display_info = lambda: self.popup(self, "About LPHK", self.about_image, + "A Novation Launchpad Macro Scripting System\nMade by Ella Jameson (nimaid)\n\nVersion: " + VERSION + "\nFile format version: " + files.FILE_VERSION, + "Done") self.m_Help.add_command(label="About LPHK", command=display_info) self.m.add_cascade(label="Help", menu=self.m_Help) @@ -134,28 +135,28 @@ def init_window(self): c_size = (BUTTON_SIZE * 9) + (c_gap * 9) self.c = tk.Canvas(self, width=c_size, height=c_size) self.c.bind("", self.click) - self.c.grid(row=0, column=0, padx=round(c_gap/2), pady=round(c_gap/2)) + self.c.grid(row=0, column=0, padx=round(c_gap / 2), pady=round(c_gap / 2)) self.stat = tk.Label(self, text="No Launchpad Connected", bg=STAT_INACTIVE_COLOR, fg="#fff") self.stat.grid(row=1, column=0, sticky=tk.EW) self.stat.config(font=("Courier", BUTTON_SIZE // 3, "bold")) - + def raise_above_all(self): self.master.attributes('-topmost', 1) self.master.attributes('-topmost', 0) - + def enable_menu(self, name): self.m.entryconfig(name, state="normal") def disable_menu(self, name): self.m.entryconfig(name, state="disabled") - + def connect_dummy(self): # WIP global lp_connected global lp_mode global lp_object - + lp_connected = False lp_mode = "Dummy" self.draw_canvas() @@ -267,7 +268,7 @@ def save_layout(self): else: files.save_lp_to_layout(files.curr_layout) files.load_layout_to_lp(files.curr_layout) - + def click(self, event): gap = int(BUTTON_SIZE // 4) @@ -275,7 +276,7 @@ def click(self, event): row = min(8, int(event.y // (BUTTON_SIZE + gap))) if self.grid_drawn: - if(column, row) == (8, 0): + if (column, row) == (8, 0): # mode change self.last_clicked = None if self.button_mode == "edit": @@ -285,7 +286,7 @@ def click(self, event): elif self.button_mode == "swap": self.button_mode = "copy" else: - self.button_mode = "edit" + self.button_mode = "edit" self.draw_canvas() else: if self.button_mode == "edit": @@ -300,22 +301,26 @@ def click(self, event): move_func = partial(scripts.move, self.last_clicked[0], self.last_clicked[1], column, row) swap_func = partial(scripts.swap, self.last_clicked[0], self.last_clicked[1], column, row) copy_func = partial(scripts.copy, self.last_clicked[0], self.last_clicked[1], column, row) - + if self.button_mode == "move": if scripts.is_bound(column, row) and ((self.last_clicked) != (column, row)): - self.popup_choice(self, "Button Already Bound", self.warning_image, "You are attempting to move a button to an already\nbound button. What would you like to do?", [["Overwrite", move_func], ["Swap", swap_func], ["Cancel", None]]) + self.popup_choice(self, "Button Already Bound", self.warning_image, + "You are attempting to move a button to an already\nbound button. What would you like to do?", + [["Overwrite", move_func], ["Swap", swap_func], ["Cancel", None]]) else: move_func() elif self.button_mode == "copy": if scripts.is_bound(column, row) and ((self.last_clicked) != (column, row)): - self.popup_choice(self, "Button Already Bound", self.warning_image, "You are attempting to copy a button to an already\nbound button. What would you like to do?", [["Overwrite", copy_func], ["Swap", swap_func], ["Cancel", None]]) + self.popup_choice(self, "Button Already Bound", self.warning_image, + "You are attempting to copy a button to an already\nbound button. What would you like to do?", + [["Overwrite", copy_func], ["Swap", swap_func], ["Cancel", None]]) else: copy_func() elif self.button_mode == "swap": swap_func() self.last_clicked = None self.draw_canvas() - + def draw_button(self, column, row, color="#000000", shape="square"): gap = int(BUTTON_SIZE // 4) @@ -328,7 +333,8 @@ def draw_button(self, column, row, color="#000000", shape="square"): return self.c.create_rectangle(x_start, y_start, x_end, y_end, fill=color, outline="") elif shape == "circle": shrink = BUTTON_SIZE / 10 - return self.c.create_oval(x_start + shrink, y_start + shrink, x_end - shrink, y_end - shrink, fill=color, outline="") + return self.c.create_oval(x_start + shrink, y_start + shrink, x_end - shrink, y_end - shrink, fill=color, + outline="") def draw_canvas(self): if self.last_clicked is not None: @@ -339,17 +345,20 @@ def draw_canvas(self): y_start = round((BUTTON_SIZE * self.last_clicked[1]) + (gap * self.last_clicked[1])) x_end = round(x_start + BUTTON_SIZE + gap) y_end = round(y_start + BUTTON_SIZE + gap) - + if (self.last_clicked[1] == 0) or (self.last_clicked[0] == 8): - self.outline_box = self.c.create_oval(x_start + (gap // 2), y_start + (gap // 2), x_end - (gap // 2), y_end - (gap // 2), fill=SELECT_COLOR, outline="") + self.outline_box = self.c.create_oval(x_start + (gap // 2), y_start + (gap // 2), + x_end - (gap // 2), y_end - (gap // 2), fill=SELECT_COLOR, + outline="") else: - self.outline_box = self.c.create_rectangle(x_start, y_start, x_end, y_end, fill=SELECT_COLOR, outline="") + self.outline_box = self.c.create_rectangle(x_start, y_start, x_end, y_end, fill=SELECT_COLOR, + outline="") self.c.tag_lower(self.outline_box) else: if self.outline_box is not None: self.c.delete(self.outline_box) self.outline_box = None - + if self.grid_drawn: for x in range(8): y = 0 @@ -362,7 +371,7 @@ def draw_canvas(self): for x in range(8): for y in range(1, 9): self.c.itemconfig(self.grid_rects[x][y], fill=lp_colors.getXY_RGB(x, y)) - + self.c.itemconfig(self.grid_rects[8][0], text=self.button_mode.capitalize()) else: for x in range(8): @@ -376,12 +385,13 @@ def draw_canvas(self): for x in range(8): for y in range(1, 9): self.grid_rects[x][y] = self.draw_button(x, y, color=lp_colors.getXY_RGB(x, y)) - + gap = int(BUTTON_SIZE // 4) text_x = round((BUTTON_SIZE * 8) + (gap * 8) + (BUTTON_SIZE / 2) + (gap / 2)) text_y = round((BUTTON_SIZE / 2) + (gap / 2)) - self.grid_rects[8][0] = self.c.create_text(text_x, text_y, text=self.button_mode.capitalize(), font=("Courier", BUTTON_SIZE // 3, "bold")) - + self.grid_rects[8][0] = self.c.create_text(text_x, text_y, text=self.button_mode.capitalize(), + font=("Courier", BUTTON_SIZE // 3, "bold")) + self.grid_drawn = True def clear_canvas(self): @@ -390,8 +400,6 @@ def clear_canvas(self): self.grid_drawn = False def script_entry_window(self, x, y, text_override=None, color_override=None): - global color_to_set - w = tk.Toplevel(self) w.winfo_toplevel().title("Editing Script for Button (" + str(x) + ", " + str(y) + ")") w.resizable(False, False) @@ -401,22 +409,25 @@ def script_entry_window(self, x, y, text_override=None, color_override=None): dummy = None # w.call('wm', 'iconphoto', w._w, tk.PhotoImage(file=MAIN_ICON)) else: - w.iconbitmap(MAIN_ICON) - + w.iconbitmap(MAIN_ICON) + def validate_func(): nonlocal x, y, t - + text_string = t.get(1.0, tk.END) try: script_validate = scripts.validate_script(text_string) except: # self.save_script(w, x, y, text_string) # This will fail and throw a popup error - self.popup(w, "Script Validation Error", self.error_image, "Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.", "OK") + self.popup(w, "Script Validation Error", self.error_image, + "Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.", + "OK") raise if script_validate != True and files.in_error: self.save_script(w, x, y, text_string) else: w.destroy() + w.protocol("WM_DELETE_WINDOW", validate_func) e_m = tk.Menu(w) @@ -426,7 +437,7 @@ def validate_func(): t = tk.scrolledtext.ScrolledText(w) t.grid(column=0, row=0, rowspan=3, padx=10, pady=10) - + if text_override is None: t.insert(tk.INSERT, scripts.text[x][y]) else: @@ -439,33 +450,37 @@ def validate_func(): export_script_func = lambda: self.export_script(t, w) e_m_Script.add_command(label="Export script", command=export_script_func) e_m.add_cascade(label="Script", menu=e_m_Script) - + if color_override is None: colors_to_set[x][y] = lp_colors.getXY(x, y) else: colors_to_set[x][y] = color_override - + if type(colors_to_set[x][y]) == int: colors_to_set[x][y] = lp_colors.code_to_RGB(colors_to_set[x][y]) - + if all(c < 4 for c in colors_to_set[x][y]): active_colors_to_set[x][y] = DEFAULT_ACTIVE_COLOR if lp_mode == "Mk1": colors_to_set[x][y] = MK1_DEFAULT_COLOR else: colors_to_set[x][y] = DEFAULT_COLOR - - ask_color_func = lambda: self.ask_color(w, color_button, x, y, colors_to_set[x][y]) + + def ask_color_func(): + color = self.ask_color(w, color_button, x, y, colors_to_set[x][y]) + colors_to_set[x][y] = color + color_button = tk.Button(w, text="Select Color", command=ask_color_func) color_button.grid(column=1, row=0, padx=(0, 5), pady=(5, 25), sticky="nesw") color_button.config(font=BUTTON_FONT) start_color_str = lp_colors.list_RGB_to_string(colors_to_set[x][y]) self.button_color_with_text_update(color_button, start_color_str) - active_color_button = tk.Button( - w, - text="Select Active Color", - command=lambda: self.ask_color(w, active_color_button, x, y, active_colors_to_set[x][y])) + def ask_active_color_func(): + color = self.ask_color(w, active_color_button, x, y, active_colors_to_set[x][y]) + active_colors_to_set[x][y] = color + + active_color_button = tk.Button(w, text="Select Active Color", command=ask_active_color_func) active_color_button.grid(column=1, row=1, padx=(0, 5), pady=(5, 25), sticky="nesw") active_color_button.config(font=BUTTON_FONT) active_color_str = lp_colors.list_RGB_to_string(active_colors_to_set[x][y]) @@ -498,51 +513,51 @@ def classic_askcolor(self, color=(255, 0, 0), title="Color Chooser"): # w.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) else: w.iconbitmap(MAIN_ICON) - + w.protocol("WM_DELETE_WINDOW", w.destroy) - + color = "" - + def return_color(col): nonlocal color color = col w.destroy() - + button_frame = tk.Frame(w) button_frame.grid(padx=(10, 0), pady=(10, 0)) - + def make_grid_button(column, row, color_hex, func=None, size=100): nonlocal w f = tk.Frame(button_frame, width=size, height=size) b = tk.Button(f, command=func) - - f.rowconfigure(0, weight = 1) - f.columnconfigure(0, weight = 1) + + f.rowconfigure(0, weight=1) + f.columnconfigure(0, weight=1) f.grid_propagate(0) - + f.grid(column=column, row=row) - b.grid(padx=(0,10), pady=(0,10), sticky="nesw") + b.grid(padx=(0, 10), pady=(0, 10), sticky="nesw") b.config(bg=color_hex) - + def make_color_button(button_color, column, row, size=100): button_color_hex = "#%02x%02x%02x" % button_color - + b_func = lambda: return_color(button_color) make_grid_button(column, row, button_color_hex, b_func, size) - + for c in range(4): for r in range(4): if not (c == 0 and r == 3): red = int(c * (255 / 3)) green = int((3 - r) * (255 / 3)) - + make_color_button((red, green, 0), c, r, size=75) w.wait_visibility() w.grab_set() w.wait_window() - + if color: hex = "#%02x%02x%02x" % color return color, hex @@ -552,18 +567,20 @@ def make_color_button(button_color, column, row, size=100): # TODO: figure out a way to make sure that we return the color instead of setting it in here def ask_color(self, window, button, x, y, default_color): global colors_to_set - + if lp_mode == "Mk1": - color = self.classic_askcolor(color=tuple(default_color), title="Select Color for Button (" + str(x) + ", " + str(y) + ")") + color = self.classic_askcolor(color=tuple(default_color), + title="Select Color for Button (" + str(x) + ", " + str(y) + ")") else: - color = tkcolorpicker.askcolor(color=tuple(default_color), parent=window, title="Select Color for Button (" + str(x) + ", " + str(y) + ")") + color = tkcolorpicker.askcolor(color=tuple(default_color), parent=window, + title="Select Color for Button (" + str(x) + ", " + str(y) + ")") if color[0] is not None: color_to_set = [int(min(255, max(0, c))) for c in color[0]] + if all(c < 4 for c in color_to_set): rerun = lambda: self.ask_color(window, button, x, y, default_color) self.popup(window, "Invalid Color", self.warning_image, "That color is too dark to see.", "OK", rerun) else: - # colors_to_set[x][y] = color_to_set self.button_color_with_text_update(button, color[1]) return color_to_set @@ -599,19 +616,22 @@ def unbind_destroy(self, x, y, window): self.draw_canvas() window.destroy() - def save_script(self, window, x, y, script_text, open_editor = False, color=None): + def save_script(self, window, x, y, script_text, open_editor=False, color=None): global colors_to_set - + script_text = script_text.strip() - + def open_editor_func(): nonlocal x, y if open_editor: - self.script_entry_window(x, y, script_text, color) + self.script_entry_window(x, y, script_text, color) + try: script_validate = scripts.validate_script(script_text) except: - self.popup(window, "Script Validation Error", self.error_image, "Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.", "OK", end_command = open_editor_func) + self.popup(window, "Script Validation Error", self.error_image, + "Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.", + "OK", end_command=open_editor_func) raise if script_validate == True: if script_text != "": @@ -621,9 +641,12 @@ def open_editor_func(): lp_colors.updateXY(x, y) window.destroy() else: - self.popup(window, "No Script Entered", self.info_image, "Please enter a script to bind.", "OK", end_command = open_editor_func) + self.popup(window, "No Script Entered", self.info_image, "Please enter a script to bind.", "OK", + end_command=open_editor_func) else: - self.popup(window, "(" + str(x) + ", " + str(y) + ") Syntax Error", self.error_image, "Error in line: " + script_validate[1] + "\n" + script_validate[0], "OK", end_command = open_editor_func) + self.popup(window, "(" + str(x) + ", " + str(y) + ") Syntax Error", self.error_image, + "Error in line: " + script_validate[1] + "\n" + script_validate[0], "OK", + end_command=open_editor_func) def import_script(self, textbox, window): name = tk.filedialog.askopenfilename(parent=window, @@ -654,7 +677,7 @@ def popup(self, window, title, image, text, button_text, end_command=None): if MAIN_ICON is not None: if os.path.splitext(MAIN_ICON)[1].lower() == ".gif": dummy = None - #popup.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) + # popup.call('wm', 'iconphoto', popup._w, tk.PhotoImage(file=MAIN_ICON)) else: popup.iconbitmap(MAIN_ICON) popup.wm_title(title) @@ -673,7 +696,7 @@ def run_end(): popup.wait_visibility() popup.grab_set() popup.wait_window() - + def popup_choice(self, window, title, image, text, choices): popup = tk.Toplevel(window) popup.resizable(False, False) @@ -685,7 +708,7 @@ def popup_choice(self, window, title, image, text, choices): popup.iconbitmap(MAIN_ICON) popup.wm_title(title) popup.tkraise(window) - + def run_end(func): popup.destroy() if func is not None: @@ -701,7 +724,7 @@ def run_end(func): popup.wait_visibility() popup.grab_set() popup.wait_window() - + def modified_layout_save_prompt(self): if files.layout_changed_since_load == True: layout_empty = True @@ -710,9 +733,11 @@ def modified_layout_save_prompt(self): if text != "": layout_empty = False break - + if not layout_empty: - self.popup_choice(self, "Save Changes?", self.warning_image, "You have made changes to this layout.\nWould you like to save this layout before exiting?", [["Save", self.save_layout], ["Save As...", self.save_layout_as], ["Discard", None]]) + self.popup_choice(self, "Save Changes?", self.warning_image, + "You have made changes to this layout.\nWould you like to save this layout before exiting?", + [["Save", self.save_layout], ["Save As...", self.save_layout_as], ["Discard", None]]) def make():