From b3f85bbe434be0077139852cc23e5cebeae5dd7b Mon Sep 17 00:00:00 2001 From: Faraphel Date: Fri, 29 Jul 2022 19:46:21 +0200 Subject: [PATCH] implemented track_formatting interface --- source/gui/preview/track_formatting.py | 62 ++++++++++++++++---------- source/mkw/MKWColor.py | 20 +++++++-- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/source/gui/preview/track_formatting.py b/source/gui/preview/track_formatting.py index f13d526..6ff2ecc 100644 --- a/source/gui/preview/track_formatting.py +++ b/source/gui/preview/track_formatting.py @@ -1,8 +1,8 @@ import tkinter from tkinter import ttk -from source.translation import translate as _ -from source.mkw.MKWColor import MKWColor +import re +from source.mkw.MKWColor import MKWColor ModConfig: any @@ -17,9 +17,13 @@ class Window(tkinter.Toplevel): self.entry_format_input.grid(row=1, column=1, sticky="NEWS") self.entry_format_input.bind("", self.preview) - self.track_preview = tkinter.Text(self) + self.track_preview = tkinter.Text(self, background="black", foreground=MKWColor("off").color_code) self.track_preview.grid(row=2, column=1, sticky="NEWS") + for color in MKWColor.get_all_colors(): + self.track_preview.tag_configure(color.bmg, foreground=color.color_code) + self.track_preview.tag_configure("error", background="red", foreground="white") + def preview(self, event: tkinter.Event = None): """ Preview all the tracks name with the track format @@ -29,30 +33,40 @@ class Window(tkinter.Toplevel): # insert all the tracks representation for track in self.mod_config.get_tracks(): - try: track_repr = track.repr_format(self.mod_config, self.entry_format_input.get()) - except: track_repr = "< ERROR >" + try: + track_repr = track.repr_format( + self.mod_config, self.entry_format_input.get() + ) - track_repr = track_repr.replace('\n', '\\n') + "\n" - self.track_preview.insert(tkinter.END, track_repr) + offset: int = 0 # the color tag is removed at every sub, so keep track of the offset + tags: list[tuple[int | None, str | None]] = [] # list of all the position of the tags, with the offset - # add the colors - for color in MKWColor.all_colors: - self.track_preview.tag_configure(color["bmg"], foreground=f"#{color['hex']:06X}") - text: str = self.track_preview.get(1.0, tkinter.END) + def tag_format(match: re.Match): + """ + Get the position of the tag and the corresponding color. Remove the tag from the string + """ + nonlocal offset, tags - tag_start: str = r"\c{" + color["bmg"] + "}" - tag_end: str = r"\c" + # add the position of the tag start + tags.append((match.span()[0] - offset, match.group("color_name"))) + offset += len(match.group()) # add the tag len to the offset since it is removed + return "" # remove the tag - find_end = -len(tag_end) + # insert into the text the track_repr without the tags + self.track_preview.insert( + tkinter.END, + re.sub(r"\\c{(?P.*?)}", tag_format, track_repr) + "\n" + ) - while find_end < len(text): - if (find_start := text.find(tag_start, find_end + len(tag_end))) == -1: break - if (find_end := text.find(tag_end, find_start + len(tag_start))) == -1: find_end = len(text) - 1 + # color every part of the track_repr with the position and color got in the re.sub + for (pos_start, tag_start), (pos_end, tag_end) in zip(tags, tags[1:] + [(None, None)]): + self.track_preview.tag_add( + tag_start, + f"end-1c-1l+{pos_start}c", + "end-1c" + (f"-1l+{pos_end}c" if pos_end is not None else "") + ) - text_start = text[:find_start].split("\n") - text_start = f"{len(text_start)}.{len(text_start[-1])}" - - text_end = text[:find_end].split("\n") - text_end = f"{len(text_end)}.{len(text_end[-1])}" - - self.track_preview.tag_add(color["bmg"], text_start, text_end) + except Exception as exc: + formatted_exc = str(exc).replace('\n', ' ') + self.track_preview.insert(tkinter.END, f"< Error: {formatted_exc} >\n") + self.track_preview.tag_add("error", "end-1c-1l", "end-1c") diff --git a/source/mkw/MKWColor.py b/source/mkw/MKWColor.py index 7207a0c..8e1d490 100644 --- a/source/mkw/MKWColor.py +++ b/source/mkw/MKWColor.py @@ -9,7 +9,7 @@ class MKWColor: Represent a color that can be used inside MKW files """ - all_colors: list[dict] = [ + _all_colors: list[dict] = [ {"bmg": "yor7", "hex": 0xF5090B, "name": "apple red"}, {"bmg": "yor6", "hex": 0xE82C09, "name": "dark red"}, {"bmg": "yor5", "hex": 0xE65118, "name": "dark orange"}, # flame @@ -28,18 +28,32 @@ class MKWColor: {"bmg": "red1", "hex": 0xE46C74, "name": "pink"}, {"bmg": "white", "hex": 0xFFFFFF, "name": "white"}, {"bmg": "clear", "hex": 0x000000, "name": "clear"}, - {"bmg": "off", "hex": 0x998C86, "name": "off"}, + {"bmg": "off", "hex": 0xDDDDDD, "name": "off"}, ] __slots__ = ("bmg", "hex", "name") def __init__(self, color_data: any, color_key: str = "name"): - colors = list(filter(lambda color: color[color_key] == color_data, self.all_colors)) + colors = list(filter(lambda color: color[color_key].upper() == color_data.upper(), self._all_colors)) if len(colors) == 0: raise ColorNotFound(color_data) for key, value in colors[0].items(): setattr(self, key, value) + @classmethod + def get_all_colors(cls): + for color in cls._all_colors: + yield cls(color["name"]) + + @property + def color_code(self) -> str: + """ + Return the color code that can be used in tkinter + :return: the color code + """ + + return f"#{self.hex:06X}" + def bmg_color_text(color_name: str, text: str) -> str: """