diff --git a/VRCT.py b/VRCT.py deleted file mode 100644 index ff7e41c8..00000000 --- a/VRCT.py +++ /dev/null @@ -1,499 +0,0 @@ -from time import sleep -from os import path as os_path - -import customtkinter -from customtkinter import CTk, CTkFrame, CTkCheckBox, CTkFont, CTkButton, CTkImage, CTkTabview, CTkTextbox, CTkEntry -from PIL.Image import open as Image_open - -from threading import Thread -from utils import print_textbox, get_localized_text, widget_main_window_label_setter -from window_config import ToplevelWindowConfig -from window_information import ToplevelWindowInformation -from config import config -from model import model - -class App(CTk): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - ## set UI theme - customtkinter.set_appearance_mode(config.APPEARANCE_THEME) - customtkinter.set_default_color_theme("blue") - - # init main window - self.iconbitmap(os_path.join(os_path.dirname(__file__), "img", "app.ico")) - self.title("VRCT") - self.geometry(f"{400}x{175}") - self.minsize(400, 175) - self.grid_columnconfigure(1, weight=1) - self.grid_rowconfigure(0, weight=1) - self.wm_attributes("-alpha", config.TRANSPARENCY/100) - customtkinter.set_widget_scaling(int(config.UI_SCALING.replace("%", "")) / 100) - self.protocol("WM_DELETE_WINDOW", self.delete_window) - - # add sidebar - self.add_sidebar() - - # add entry message box - self.entry_message_box = CTkEntry( - self, - placeholder_text="message", - font=CTkFont(family=config.FONT_FAMILY), - ) - self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=5, pady=(5, 10), sticky="nsew") - self.entry_message_box.bind("", self.entry_message_box_press_key_enter) - self.entry_message_box.bind("", self.entry_message_box_press_key_any) - self.entry_message_box.bind("", self.entry_message_box_leave) - - # add tabview textbox - self.add_tabview_logs(get_localized_text(f"{config.UI_LANGUAGE}")) - - self.config_window = ToplevelWindowConfig(self) - self.information_window = ToplevelWindowInformation(self) - self.init_process() - - def init_process(self): - # set translator - if model.authenticationTranslator() is False: - # error update Auth key - self.printLogAuthenticationError() - - # set word filter - model.addKeywords() - - # check OSC started - model.checkOSCStarted() - - # check Software Updated - model.checkSoftwareUpdated() - - def button_config_callback(self): - self.foreground_stop() - self.transcription_stop() - self.checkbox_translation.configure(state="disabled") - self.checkbox_transcription_send.configure(state="disabled") - self.checkbox_transcription_receive.configure(state="disabled") - self.checkbox_foreground.configure(state="disabled") - self.tabview_logs.configure(state="disabled") - self.textbox_message_log.configure(state="disabled") - self.textbox_message_send_log.configure(state="disabled") - self.textbox_message_receive_log.configure(state="disabled") - self.textbox_message_system_log.configure(state="disabled") - self.entry_message_box.configure(state="disabled") - self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) - self.button_information.configure(state="disabled", fg_color=["gray92", "gray14"]) - self.config_window.deiconify() - self.config_window.focus_set() - self.config_window.focus() - self.config_window.grab_set() - - def button_information_callback(self): - self.information_window.deiconify() - self.information_window.focus_set() - self.information_window.focus() - - def checkbox_translation_callback(self): - config.ENABLE_TRANSLATION = self.checkbox_translation.get() - if config.ENABLE_TRANSLATION is True: - self.printLogStartTranslation() - else: - self.printLogStopTranslation() - - def transcription_send_start(self): - model.startMicTranscript(self.sendMicMessage) - self.printLogStartVoice2chatbox() - self.checkbox_transcription_send.configure(state="normal") - self.checkbox_transcription_receive.configure(state="normal") - self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) - - def transcription_send_stop(self): - model.stopMicTranscript() - self.printLogStopVoice2chatbox() - self.checkbox_transcription_send.configure(state="normal") - self.checkbox_transcription_receive.configure(state="normal") - self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) - - def transcription_send_stop_for_config(self): - model.stopMicTranscript() - self.printLogStopVoice2chatbox() - - def checkbox_transcription_send_callback(self): - config.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get() - self.checkbox_transcription_send.configure(state="disabled") - self.checkbox_transcription_receive.configure(state="disabled") - self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) - if config.ENABLE_TRANSCRIPTION_SEND is True: - th_transcription_send_start = Thread(target=self.transcription_send_start) - th_transcription_send_start.daemon = True - th_transcription_send_start.start() - else: - th_transcription_send_stop = Thread(target=self.transcription_send_stop) - th_transcription_send_stop.daemon = True - th_transcription_send_stop.start() - - def transcription_receive_start(self): - model.startSpeakerTranscript(self.receiveSpeakerMessage) - self.printLogStartSpeaker2log() - self.checkbox_transcription_send.configure(state="normal") - self.checkbox_transcription_receive.configure(state="normal") - self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) - - def transcription_receive_stop(self): - model.stopSpeakerTranscript() - self.printLogStopSpeaker2log() - self.checkbox_transcription_send.configure(state="normal") - self.checkbox_transcription_receive.configure(state="normal") - self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"]) - - def transcription_receive_stop_for_config(self): - model.stopSpeakerTranscript() - self.printLogStopSpeaker2log() - - def checkbox_transcription_receive_callback(self): - config.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get() - self.checkbox_transcription_send.configure(state="disabled") - self.checkbox_transcription_receive.configure(state="disabled") - self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"]) - if config.ENABLE_TRANSCRIPTION_RECEIVE is True: - th_transcription_receive_start = Thread(target=self.transcription_receive_start) - th_transcription_receive_start.daemon = True - th_transcription_receive_start.start() - else: - th_transcription_receive_stop = Thread(target=self.transcription_receive_stop) - th_transcription_receive_stop.daemon = True - th_transcription_receive_stop.start() - - def transcription_start(self): - if config.ENABLE_TRANSCRIPTION_SEND is True: - th_transcription_send_start = Thread(target=self.transcription_send_start) - th_transcription_send_start.daemon = True - th_transcription_send_start.start() - sleep(2) - if config.ENABLE_TRANSCRIPTION_RECEIVE is True: - th_transcription_receive_start = Thread(target=self.transcription_receive_start) - th_transcription_receive_start.daemon = True - th_transcription_receive_start.start() - - def transcription_stop(self): - if config.ENABLE_TRANSCRIPTION_SEND is True: - th_transcription_send_stop = Thread(target=self.transcription_send_stop_for_config) - th_transcription_send_stop.daemon = True - th_transcription_send_stop.start() - if config.ENABLE_TRANSCRIPTION_RECEIVE is True: - th_transcription_receive_stop = Thread(target=self.transcription_receive_stop_for_config) - th_transcription_receive_stop.daemon = True - th_transcription_receive_stop.start() - - def checkbox_foreground_callback(self): - config.ENABLE_FOREGROUND = self.checkbox_foreground.get() - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", True) - self.printLogStartForeground() - else: - self.attributes("-topmost", False) - self.printLogStopForeground() - - def foreground_start(self): - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", True) - self.printLogStartForeground() - - def foreground_stop(self): - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", False) - self.printLogStopForeground() - - def entry_message_box_press_key_enter(self, event): - # osc stop send typing - model.oscStopSendTyping() - - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", True) - - message = self.entry_message_box.get() - self.sendChatMessage(message) - - def entry_message_box_press_key_any(self, event): - # osc start send typing - model.oscStartSendTyping() - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", False) - - if event.keysym != "??": - if len(event.char) != 0 and event.keysym in config.BREAK_KEYSYM_LIST: - self.entry_message_box.insert("end", event.char) - return "break" - - def entry_message_box_leave(self, event): - # osc stop send typing - model.oscStopSendTyping() - if config.ENABLE_FOREGROUND: - self.attributes("-topmost", True) - - def delete_window(self): - self.quit() - self.destroy() - - def add_sidebar(self): - init_lang_text = "Loading..." - self.sidebar_frame = CTkFrame(master=self, corner_radius=0) - - # add checkbox translation - self.checkbox_translation = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_translation_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add checkbox transcription send - self.checkbox_transcription_send = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_transcription_send_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add checkbox transcription receive - self.checkbox_transcription_receive = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_transcription_receive_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add checkbox foreground - self.checkbox_foreground = CTkCheckBox( - self.sidebar_frame, - text=init_lang_text, - onvalue=True, - offvalue=False, - command=self.checkbox_foreground_callback, - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add button information - self.button_information = CTkButton( - self.sidebar_frame, - text=None, - width=36, - command=self.button_information_callback, - image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "info-icon-white.png"))) - ) - - # add button config - self.button_config = CTkButton( - self.sidebar_frame, - text=None, - width=36, - command=self.button_config_callback, - image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png"))) - ) - - self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsw") - self.sidebar_frame.grid_rowconfigure(5, weight=1) - self.checkbox_translation.grid(row=0, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - self.checkbox_transcription_send.grid(row=1, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - self.checkbox_transcription_receive.grid(row=2, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - self.checkbox_foreground.grid(row=3, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we") - self.button_information.grid(row=5, column=0, padx=(10, 5), pady=(5, 5), sticky="wse") - self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse") - - def delete_tabview_logs(self, pre_language_yaml_data): - self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_log"]) - self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_send"]) - self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_receive"]) - self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_system"]) - - def add_tabview_logs(self, language_yaml_data): - main_tab_title_log = language_yaml_data["main_tab_title_log"] - main_tab_title_send = language_yaml_data["main_tab_title_send"] - main_tab_title_receive = language_yaml_data["main_tab_title_receive"] - main_tab_title_system = language_yaml_data["main_tab_title_system"] - - # add tabview textbox - self.tabview_logs = CTkTabview(master=self) - self.tabview_logs.add(main_tab_title_log) - self.tabview_logs.add(main_tab_title_send) - self.tabview_logs.add(main_tab_title_receive) - self.tabview_logs.add(main_tab_title_system) - self.tabview_logs.grid(row=0, column=1, padx=0, pady=0, sticky="nsew") - self.tabview_logs._segmented_button.configure(font=CTkFont(family=config.FONT_FAMILY)) - self.tabview_logs._segmented_button.grid(sticky="W") - self.tabview_logs.tab(main_tab_title_log).grid_rowconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_log).grid_columnconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_send).grid_rowconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_send).grid_columnconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_receive).grid_rowconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_receive).grid_columnconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_system).grid_rowconfigure(0, weight=1) - self.tabview_logs.tab(main_tab_title_system).grid_columnconfigure(0, weight=1) - self.tabview_logs.configure(fg_color="transparent") - - # add textbox message log - self.textbox_message_log = CTkTextbox( - self.tabview_logs.tab(main_tab_title_log), - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add textbox message send log - self.textbox_message_send_log = CTkTextbox( - self.tabview_logs.tab(main_tab_title_send), - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add textbox message receive log - self.textbox_message_receive_log = CTkTextbox( - self.tabview_logs.tab(main_tab_title_receive), - font=CTkFont(family=config.FONT_FAMILY) - ) - - # add textbox message system log - self.textbox_message_system_log = CTkTextbox( - self.tabview_logs.tab(main_tab_title_system), - font=CTkFont(family=config.FONT_FAMILY) - ) - - self.textbox_message_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_send_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_receive_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_system_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew") - self.textbox_message_log.configure(state='disabled') - self.textbox_message_send_log.configure(state='disabled') - self.textbox_message_receive_log.configure(state='disabled') - self.textbox_message_system_log.configure(state='disabled') - - widget_main_window_label_setter(self, language_yaml_data) - - def printLogAuthenticationError(self): - print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR") - print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR") - - def printLogStartTranslation(self): - print_textbox(self.textbox_message_log, "Start translation", "INFO") - print_textbox(self.textbox_message_system_log, "Start translation", "INFO") - - def printLogStopTranslation(self): - print_textbox(self.textbox_message_log, "Stop translation", "INFO") - print_textbox(self.textbox_message_system_log, "Stop translation", "INFO") - - def printLogStartVoice2chatbox(self): - print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO") - print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO") - - def printLogStopVoice2chatbox(self): - print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO") - print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO") - - def printLogStartSpeaker2log(self): - print_textbox(self.textbox_message_log, "Start speaker2log", "INFO") - print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO") - - def printLogStopSpeaker2log(self): - print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO") - print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO") - - def printLogStartForeground(self): - print_textbox(self.textbox_message_log, "Start foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Start foreground", "INFO") - - def printLogStopForeground(self): - print_textbox(self.textbox_message_log, "Stop foreground", "INFO") - print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO") - - def printLogDetectWordFilter(self, message): - print_textbox(self.textbox_message_log, f"Detect WordFilter :{message}", "INFO") - print_textbox(self.textbox_message_system_log, f"Detect WordFilter :{message}", "INFO") - - def printLogOSCError(self): - print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR") - - def printLogSendMessage(self, message): - print_textbox(self.textbox_message_log, f"{message}", "SEND") - print_textbox(self.textbox_message_send_log, f"{message}", "SEND") - - def printLogReceiveMessage(self, message): - print_textbox(self.textbox_message_log, f"{message}", "RECEIVE") - print_textbox(self.textbox_message_receive_log, f"{message}", "RECEIVE") - - def sendChatMessage(self, message): - if len(message) > 0: - # translate - if config.ENABLE_TRANSLATION is False: - chat_message = f"{message}" - elif model.getTranslatorStatus() is False: - self.printLogAuthenticationError() - chat_message = f"{message}" - else: - chat_message = model.getInputTranslate(message) - - # send OSC message - if config.ENABLE_OSC is True: - model.oscSendMessage(chat_message) - else: - self.printLogOSCError() - - # update textbox message log - self.printLogSendMessage(chat_message) - - # delete message in entry message box - if config.ENABLE_AUTO_CLEAR_CHATBOX is True: - self.entry_message_box.delete(0, customtkinter.END) - - def sendMicMessage(self, message): - if len(message) > 0: - # word filter - if model.checkKeywords(message): - self.printLogDetectWordFilter(message) - return - - # translate - if config.ENABLE_TRANSLATION is False: - voice_message = f"{message}" - elif model.getTranslatorStatus() is False: - self.printLogAuthenticationError() - voice_message = f"{message}" - else: - voice_message = model.getInputTranslate(message) - - if config.ENABLE_TRANSCRIPTION_SEND is True: - if config.ENABLE_OSC is True: - # osc send message - model.oscSendMessage(voice_message) - else: - self.printLogOSCError() - # update textbox message log - self.printLogSendMessage(voice_message) - - def receiveSpeakerMessage(self, message): - if len(message) > 0: - # translate - if config.ENABLE_TRANSLATION is False: - voice_message = f"{message}" - elif model.getTranslatorStatus() is False: - self.printLogAuthenticationError() - voice_message = f"{message}" - else: - voice_message = model.getOutputTranslate(message) - - if config.ENABLE_TRANSCRIPTION_RECEIVE is True: - # update textbox message receive log - self.printLogReceiveMessage(voice_message) - if config.ENABLE_NOTICE_XSOVERLAY is True: - model.notificationXsoverlay(voice_message) - -if __name__ == "__main__": - try: - app = App() - app.mainloop() - except Exception as e: - import traceback - with open('error.log', 'a') as f: - traceback.print_exc(file=f) \ No newline at end of file diff --git a/ctk_scrollable_dropdown.py b/ctk_scrollable_dropdown.py index 81b98205..f0f48c3e 100644 --- a/ctk_scrollable_dropdown.py +++ b/ctk_scrollable_dropdown.py @@ -15,19 +15,25 @@ import time class CTkScrollableDropdown(customtkinter.CTkToplevel): def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None, - fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None, + fg_color=None, max_button_height: int = 20, justify="center", scrollbar_button_color=None, scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[], - command=None, image_values=[], alpha: float = 0.97, frame_corner_radius=20, double_click=False, - resize=True, frame_border_color=None, text_color=None, autocomplete=False, **button_kwargs): + command=None, image_values=[], alpha: float = 0.97, double_click=False, + resize=True, frame_border_color=None, text_color=None, autocomplete=False, + max_height: int = None, button_pady: int = 0, min_show_button_num: int = 1, + button_corner_radius: int = None, frame_corner_radius=0, + **button_kwargs): super().__init__(takefocus=1) self.transient(self.master) self.alpha = alpha self.attach = attach self.corner = frame_corner_radius + # とりあえずframe_corner_radiusはframe_corner_radiusの名前のまま使いたい + self.frame_corner_radius = frame_corner_radius self.padding = 0 self.focus_something = False self.disable = True + self.font_size = 12 if button_kwargs.get("font", None) is None else button_kwargs["font"]._size if sys.platform.startswith("win"): self.after(100, lambda: self.overrideredirect(True)) @@ -48,7 +54,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.hide = True self.attach.bind('', lambda e: self._withdraw() if not self.disable else None, add="+") self.attach.winfo_toplevel().bind('', lambda e: self._withdraw() if not self.disable else None, add="+") - self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") + self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") self.attach.winfo_toplevel().bind("", lambda e: self._withdraw() if not self.disable else None, add="+") @@ -84,6 +90,10 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.autocomplete = autocomplete self.var_update = customtkinter.StringVar() self.appear = False + self.max_height = max_height + self.button_pady = button_pady + self.min_show_button_num = min_show_button_num + self.button_corner_radius = button_corner_radius if justify.lower()=="left": self.justify = "w" @@ -92,7 +102,7 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): else: self.justify = "c" - self.button_height = button_height + self.button_height = max_button_height + self.font_size self.values = values self.button_num = len(self.values) self.image_values = None if len(image_values)!=len(self.values) else image_values @@ -179,8 +189,10 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): text_color=self.text_color, image=self.image_values[i] if self.image_values is not None else None, anchor=self.justify, + corner_radius= self.button_corner_radius, command=lambda k=row: self._attach_key_press(k), **button_kwargs) - self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0)) + pady = 0 if self.button_num-1 == self.i else self.button_pady + self.widgets[self.i].pack(fill="x", pady=(0, pady), padx=(self.padding, 0)) self.i+=1 self.hide = False @@ -195,12 +207,25 @@ class CTkScrollableDropdown(customtkinter.CTkToplevel): self.width_new = self.attach.winfo_width() if self.width is None else self.width if self.resize: - if self.button_num==1: - self.height_new = self.button_height * self.button_num + 45 + button_height_include_pady = self.button_height + self.button_pady + + if self.min_show_button_num < self.button_num: + min_buttons_height = button_height_include_pady * self.min_show_button_num else: - self.height_new = self.button_height * self.button_num + 35 - if self.height_new>self.height: - self.height_new = self.height + min_buttons_height = button_height_include_pady * self.button_num + # delete last one's pady px + min_buttons_height -= self.button_pady + + # minor adjustment + 5px + min_buttons_height += 5 + # adjust by frame_corner_radius + min_buttons_height += (self.frame_corner_radius * 2) + + if self.max_height: + if min_buttons_height>self.max_height: + min_buttons_height = self.max_height + + self.height_new = min_buttons_height self.geometry('{}x{}+{}+{}'.format(self.width_new, self.height_new, self.x_pos, self.y_pos)) diff --git a/img/arrow_left_disabled.png b/img/arrow_left_disabled.png new file mode 100644 index 00000000..5b5f3afa Binary files /dev/null and b/img/arrow_left_disabled.png differ diff --git a/img/arrow_left_white.png b/img/arrow_left_white.png new file mode 100644 index 00000000..463d8a74 Binary files /dev/null and b/img/arrow_left_white.png differ diff --git a/img/configuration_icon_disabled.png b/img/configuration_icon_disabled.png new file mode 100644 index 00000000..03a4a217 Binary files /dev/null and b/img/configuration_icon_disabled.png differ diff --git a/img/configuration_icon_white.png b/img/configuration_icon_white.png new file mode 100644 index 00000000..ee6e050e Binary files /dev/null and b/img/configuration_icon_white.png differ diff --git a/img/foreground_icon_disabled.png b/img/foreground_icon_disabled.png new file mode 100644 index 00000000..91778b7b Binary files /dev/null and b/img/foreground_icon_disabled.png differ diff --git a/img/foreground_icon_white.png b/img/foreground_icon_white.png new file mode 100644 index 00000000..50370ad1 Binary files /dev/null and b/img/foreground_icon_white.png differ diff --git a/img/headphones_icon_disabled.png b/img/headphones_icon_disabled.png new file mode 100644 index 00000000..f81f812e Binary files /dev/null and b/img/headphones_icon_disabled.png differ diff --git a/img/headphones_icon_white.png b/img/headphones_icon_white.png new file mode 100644 index 00000000..54f7359d Binary files /dev/null and b/img/headphones_icon_white.png differ diff --git a/img/help_icon_disabled.png b/img/help_icon_disabled.png new file mode 100644 index 00000000..03e1c086 Binary files /dev/null and b/img/help_icon_disabled.png differ diff --git a/img/help_icon_white.png b/img/help_icon_white.png new file mode 100644 index 00000000..ee5cb936 Binary files /dev/null and b/img/help_icon_white.png differ diff --git a/img/mic_icon_disabled.png b/img/mic_icon_disabled.png new file mode 100644 index 00000000..542d2824 Binary files /dev/null and b/img/mic_icon_disabled.png differ diff --git a/img/mic_icon_white.png b/img/mic_icon_white.png new file mode 100644 index 00000000..e1837463 Binary files /dev/null and b/img/mic_icon_white.png differ diff --git a/img/narrow_arrow_down.png b/img/narrow_arrow_down.png new file mode 100644 index 00000000..309560c8 Binary files /dev/null and b/img/narrow_arrow_down.png differ diff --git a/img/translation_icon_disabled.png b/img/translation_icon_disabled.png new file mode 100644 index 00000000..533feb81 Binary files /dev/null and b/img/translation_icon_disabled.png differ diff --git a/img/translation_icon_white.png b/img/translation_icon_white.png new file mode 100644 index 00000000..706b0bbc Binary files /dev/null and b/img/translation_icon_white.png differ diff --git a/img/vrct_logo_for_dark_mode.png b/img/vrct_logo_for_dark_mode.png new file mode 100644 index 00000000..7eeaabc2 Binary files /dev/null and b/img/vrct_logo_for_dark_mode.png differ diff --git a/img/vrct_logo_for_light_mode.png b/img/vrct_logo_for_light_mode.png new file mode 100644 index 00000000..75b1afd9 Binary files /dev/null and b/img/vrct_logo_for_light_mode.png differ diff --git a/img/vrct_logo_mark_black.png b/img/vrct_logo_mark_black.png new file mode 100644 index 00000000..7a593e8c Binary files /dev/null and b/img/vrct_logo_mark_black.png differ diff --git a/img/vrct_logo_mark_white.png b/img/vrct_logo_mark_white.png new file mode 100644 index 00000000..0a6f1968 Binary files /dev/null and b/img/vrct_logo_mark_white.png differ diff --git a/main.py b/main.py new file mode 100644 index 00000000..ac80e5f5 --- /dev/null +++ b/main.py @@ -0,0 +1,8 @@ +from vrct_gui import vrct_gui + +class VRCT(): + def __init__(self): + pass +if __name__ == "__main__": + # vrct_gui = VRCT_GUI() + vrct_gui.start() \ No newline at end of file diff --git a/utils.py b/utils.py index 2bee5814..3033cb13 100644 --- a/utils.py +++ b/utils.py @@ -1,106 +1,6 @@ from os import path as os_path -import yaml -from datetime import datetime +from PIL.Image import open as Image_open -def print_textbox(textbox, message, tags=None): - now = datetime.now() - now = now.strftime('%H:%M:%S') - - textbox.tag_config("ERROR", foreground="#FF0000") - textbox.tag_config("INFO", foreground="#1BFF00") - textbox.tag_config("SEND", foreground="#0378e2") - textbox.tag_config("RECEIVE", foreground="#ffa500") - - textbox.configure(state='normal') - textbox.insert("end", f"[{now}][") - textbox.insert("end", f"{tags}", tags) - textbox.insert("end", f"]{message}\n") - textbox.configure(state='disabled') - textbox.see("end") - -def get_localized_text(language): - file_path = os_path.join(os_path.dirname(__file__), "locales.yml") - - with open(file_path, encoding="utf-8") as file: - languages_yaml_data = yaml.safe_load(file) - default_language = "en" - if language in languages_yaml_data: - localized_text = languages_yaml_data[language] - if default_language in languages_yaml_data: - default_text = languages_yaml_data[default_language] - merged_text = {**default_text, **localized_text} - return merged_text - else: - return localized_text - else: - return None - -def get_key_by_value(dictionary, value): - for key, val in dictionary.items(): - if val == value: - return key - return None - -def widget_config_window_label_setter(self, language_yaml_data): - widget_names = [ - # tab UI - "label_transparency", - "label_appearance_theme", - "label_ui_scaling", - "label_font_family", - "label_ui_language", - - # tab Translation - "label_translation_translator", - "label_translation_input_language", - "label_translation_output_language", - - # tab Transcription - "label_input_mic_host", - "label_input_mic_device", - "label_input_mic_voice_language", - "label_input_mic_energy_threshold", - "checkbox_input_mic_threshold_check", - "label_input_mic_dynamic_energy_threshold", - "label_input_mic_record_timeout", - "label_input_mic_phrase_timeout", - "label_input_mic_max_phrases", - "label_input_mic_word_filter", - - "label_input_speaker_device", - "label_input_speaker_voice_language", - "label_input_speaker_energy_threshold", - "checkbox_input_speaker_threshold_check", - "label_input_speaker_dynamic_energy_threshold", - "label_input_speaker_record_timeout", - "label_input_speaker_phrase_timeout", - "label_input_speaker_max_phrases", - - # tab Parameter - "label_ip_address", - "label_port", - "label_authkey", - "label_message_format", - - # tab Others - "label_checkbox_auto_clear_chatbox", - "label_checkbox_notice_xsoverlay", - ] - for name in widget_names: - widget = getattr(self, name) - text_value = language_yaml_data.get(name) - if widget is not None and text_value is not None: - widget.configure(text=text_value + ":") - -def widget_main_window_label_setter(self, language_yaml_data): - widget_names = [ - "checkbox_translation", - "checkbox_transcription_send", - "checkbox_transcription_receive", - "checkbox_foreground", - ] - for name in widget_names: - widget = getattr(self, name) - text_value = language_yaml_data.get(name) - if widget is not None and text_value is not None: - widget.configure(text=text_value) \ No newline at end of file +def getImageFile(file_name): + img = Image_open(os_path.join(os_path.dirname(__file__), "img", file_name)) + return img \ No newline at end of file diff --git a/vrct_gui/__init__.py b/vrct_gui/__init__.py new file mode 100644 index 00000000..5c2e8cca --- /dev/null +++ b/vrct_gui/__init__.py @@ -0,0 +1 @@ +from .vrct_gui import vrct_gui \ No newline at end of file diff --git a/vrct_gui/_changeMainWindowWidgetsStatus.py b/vrct_gui/_changeMainWindowWidgetsStatus.py new file mode 100644 index 00000000..602555c2 --- /dev/null +++ b/vrct_gui/_changeMainWindowWidgetsStatus.py @@ -0,0 +1,148 @@ +from customtkinter import CTkImage + +from .ui_utils import getImageFileFromUiUtils + + +def _changeMainWindowWidgetsStatus(vrct_gui, settings, status, target_names): + COMPACT_MODE_ICON_SIZE_TUPLES = (settings.COMPACT_MODE_ICON_SIZE, settings.COMPACT_MODE_ICON_SIZE) + + if target_names == "All": + target_names = ["translation_switch", "transcription_send_switch", "transcription_receive_switch", "foreground_switch", "quick_language_settings", "config_button", "minimize_sidebar_button", "entry_message_box"] + + + + + def update_switch_status(widget_frame, widget_label, widget_switch_box, widget_selected_mark, widget_compact_mode_icon, icon_name, disabled_icon_name): + if status == "disabled": + widget_frame.configure(cursor="") + widget_label.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR) + widget_switch_box.configure(state="disabled", progress_color=settings.ctm.SF__SWITCH_BOX_DISABLE_BG_COLOR) + widget_selected_mark.configure(fg_color=settings.ctm.SF__SELECTED_MARK_DISABLE_BG_COLOR) + icon_filename = disabled_icon_name + elif status == "normal": + widget_frame.configure(cursor="hand2") + widget_label.configure(text_color=settings.ctm.LABELS_TEXT_COLOR) + widget_switch_box.configure(state="normal", progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR) + widget_selected_mark.configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR) + icon_filename = icon_name + + image = CTkImage(getImageFileFromUiUtils(icon_filename), size=COMPACT_MODE_ICON_SIZE_TUPLES) + widget_compact_mode_icon.configure(image=image) + + + + + for target_name in target_names: + match target_name: + case "translation_switch": + update_switch_status( + widget_frame=vrct_gui.translation_frame, + widget_label=vrct_gui.label_translation, + widget_switch_box=vrct_gui.translation_switch_box, + widget_selected_mark=vrct_gui.translation_selected_mark, + widget_compact_mode_icon=vrct_gui.translation_compact_mode_icon, + icon_name=settings.image_filename.TRANSLATION_ICON, + disabled_icon_name=settings.image_filename.TRANSLATION_ICON_DISABLED + ) + case "transcription_send_switch": + update_switch_status( + widget_frame=vrct_gui.transcription_send_frame, + widget_label=vrct_gui.label_transcription_send, + widget_switch_box=vrct_gui.transcription_send_switch_box, + widget_selected_mark=vrct_gui.transcription_send_selected_mark, + widget_compact_mode_icon=vrct_gui.transcription_send_compact_mode_icon, + icon_name=settings.image_filename.MIC_ICON, + disabled_icon_name=settings.image_filename.MIC_ICON_DISABLED + ) + case "transcription_receive_switch": + update_switch_status( + widget_frame=vrct_gui.transcription_receive_frame, + widget_label=vrct_gui.label_transcription_receive, + widget_switch_box=vrct_gui.transcription_receive_switch_box, + widget_selected_mark=vrct_gui.transcription_receive_selected_mark, + widget_compact_mode_icon=vrct_gui.transcription_receive_compact_mode_icon, + icon_name=settings.image_filename.HEADPHONES_ICON, + disabled_icon_name=settings.image_filename.HEADPHONES_ICON_DISABLED + ) + case "foreground_switch": + update_switch_status( + widget_frame=vrct_gui.foreground_frame, + widget_label=vrct_gui.label_foreground, + widget_switch_box=vrct_gui.foreground_switch_box, + widget_selected_mark=vrct_gui.foreground_selected_mark, + widget_compact_mode_icon=vrct_gui.foreground_compact_mode_icon, + icon_name=settings.image_filename.FOREGROUND_ICON, + disabled_icon_name=settings.image_filename.FOREGROUND_ICON_DISABLED + ) + + + + + + + case "quick_language_settings": + if status == "disabled": + vrct_gui.sqls__container_title.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR) + vrct_gui.sqls__title_text_your_language.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR) + vrct_gui.sqls__title_text_target_language.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR) + vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE) + vrct_gui.sqls__optionmenu_your_language.configure(state="disabled") + vrct_gui.sqls__optionmenu_target_language.configure(state="disabled") + + elif status == "normal": + vrct_gui.sqls__container_title.configure(text_color=settings.ctm.LABELS_TEXT_COLOR) + vrct_gui.sqls__title_text_your_language.configure(text_color=settings.ctm.LABELS_TEXT_COLOR) + vrct_gui.sqls__title_text_target_language.configure(text_color=settings.ctm.LABELS_TEXT_COLOR) + vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR) + vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR) + vrct_gui.sqls__optionmenu_your_language.configure(state="normal") + vrct_gui.sqls__optionmenu_target_language.configure(state="normal") + + + case "config_button": + if status == "disabled": + vrct_gui.sidebar_config_button_wrapper.configure(cursor="") + vrct_gui.sidebar_config_button.configure( + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.CONFIGURATION_ICON_DISABLED)), + ) + elif status == "normal": + vrct_gui.sidebar_config_button_wrapper.configure(cursor="hand2") + vrct_gui.sidebar_config_button.configure( + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.CONFIGURATION_ICON)), + ) + + + case "minimize_sidebar_button": + LOGO_SIZE = vrct_gui.minimize_sidebar_button.cget("image").cget("size") + if status == "disabled": + vrct_gui.minimize_sidebar_button_container.configure(cursor="") + + + if settings.IS_SIDEBAR_COMPACT_MODE is True: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT_DISABLED).rotate(180), size=LOGO_SIZE) + else: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT_DISABLED), size=LOGO_SIZE) + vrct_gui.minimize_sidebar_button.configure(image=image_file) + + elif status == "normal": + vrct_gui.minimize_sidebar_button_container.configure(cursor="hand2") + if settings.IS_SIDEBAR_COMPACT_MODE is True: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT).rotate(180), size=LOGO_SIZE) + else: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT), size=LOGO_SIZE) + vrct_gui.minimize_sidebar_button.configure(image=image_file) + + + case "entry_message_box": + if status == "disabled": + vrct_gui.entry_message_box.configure(state="disabled", placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR, text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR) + elif status == "normal": + vrct_gui.entry_message_box.configure(state="normal", placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_COLOR, text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_COLOR) + + + case _: + raise ValueError(f"No matching case for target_name: {target_name}") + + + + vrct_gui.update() \ No newline at end of file diff --git a/vrct_gui/_printToTextbox.py b/vrct_gui/_printToTextbox.py new file mode 100644 index 00000000..c0a696c7 --- /dev/null +++ b/vrct_gui/_printToTextbox.py @@ -0,0 +1,37 @@ +from datetime import datetime +from customtkinter import CTkFont +from config import config + + +def _printToTextbox(settings, target_textbox, original_message, translated_message, tags=None): + now_raw_data = datetime.now() + now = now_raw_data.strftime('%H:%M:%S') + now_hm = now_raw_data.strftime('%H:%M') + + target_textbox.tag_config("NORMAL_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_COLOR) + + target_textbox.tag_config("ERROR", foreground="#FF0000") + + target_textbox.tag_config("INFO", justify="center") + target_textbox.tag_config("INFO_COLOR", foreground="#1BFF00") + + target_textbox.tag_config("SEND", justify="left") + target_textbox.tag_config("SEND_COLOR", foreground="#0378e2") + + target_textbox.tag_config("RECEIVE", justify="left") + target_textbox.tag_config("RECEIVE_COLOR", foreground="#ffa500") + + target_textbox._textbox.tag_configure("START", spacing1=10) + + target_textbox._textbox.tag_configure("LABEL", font=CTkFont(family=config.FONT_FAMILY, size=12, weight="normal")) + target_textbox._textbox.tag_configure("TIMESTAMP", font=CTkFont(family=config.FONT_FAMILY, size=12, weight="normal")) + target_textbox._textbox.tag_configure("ORIGINAL_MESSAGE", font=CTkFont(family=config.FONT_FAMILY, size=12, weight="normal")) + target_textbox._textbox.tag_configure("TRANSLATED_MESSAGE", font=CTkFont(family=config.FONT_FAMILY, size=16, weight="normal")) + + target_textbox.configure(state='normal') + target_textbox.insert("end", f"[{tags}] ", ("START", "LABEL", tags, f"{tags}_COLOR")) + target_textbox.insert("end", f"{now_hm} ", ("TIMESTAMP", tags)) + target_textbox.insert("end", f"{original_message}\n", ("ORIGINAL_MESSAGE", "NORMAL_TEXT", tags)) + target_textbox.insert("end", f"{translated_message}\n", ("TRANSLATED_MESSAGE", "NORMAL_TEXT", tags)) + target_textbox.configure(state='disabled') + target_textbox.see("end") \ No newline at end of file diff --git a/vrct_gui/config_window/ConfigWindow.py b/vrct_gui/config_window/ConfigWindow.py new file mode 100644 index 00000000..bcee1594 --- /dev/null +++ b/vrct_gui/config_window/ConfigWindow.py @@ -0,0 +1,36 @@ +from .widgets import createConfigWindowTitle, createSettingBoxTitle, createSideMenuAndSettingsBoxContainers + +from customtkinter import CTkToplevel + +from ..ui_utils import setDefaultActiveTab + +from config import config + +class ConfigWindow(CTkToplevel): + def __init__(self, vrct_gui, settings): + super().__init__() + + self.INPUT_MIC_RECORD_TIMEOUT = 3 + self.INPUT_SOURCE_LANG = "aaaaaaaaa" + self.INPUT_SPEAKER_ENERGY_THRESHOLD = 300 + self.MAX_SPEAKER_ENERGY_THRESHOLD = 4000 + self.INPUT_MIC_PHRASE_TIMEOUT = 3 + + + # configure window + self.title("test config_window.py") + self.geometry(f"{1080}x{680}") + + + self.configure(fg_color="#ff7f50") + self.protocol("WM_DELETE_WINDOW", vrct_gui.closeConfigWindow) + + + + + createConfigWindowTitle(config_window=self, settings=settings) + + createSettingBoxTitle(config_window=self, settings=settings) + + + createSideMenuAndSettingsBoxContainers(config_window=self, settings=settings) diff --git a/vrct_gui/config_window/__init__.py b/vrct_gui/config_window/__init__.py new file mode 100644 index 00000000..c6dbe941 --- /dev/null +++ b/vrct_gui/config_window/__init__.py @@ -0,0 +1 @@ +from .ConfigWindow import ConfigWindow \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/__init__.py b/vrct_gui/config_window/widgets/__init__.py new file mode 100644 index 00000000..08f2304b --- /dev/null +++ b/vrct_gui/config_window/widgets/__init__.py @@ -0,0 +1,4 @@ +from .createConfigWindowTitle import createConfigWindowTitle +from .createSettingBoxTitle import createSettingBoxTitle + +from .createSideMenuAndSettingsBoxContainers import createSideMenuAndSettingsBoxContainers \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/createConfigWindowTitle.py b/vrct_gui/config_window/widgets/createConfigWindowTitle.py new file mode 100644 index 00000000..bbbd9606 --- /dev/null +++ b/vrct_gui/config_window/widgets/createConfigWindowTitle.py @@ -0,0 +1,39 @@ +from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkImage + +from ...ui_utils import getImageFileFromUiUtils + + +def createConfigWindowTitle(config_window, settings): + + config_window.grid_columnconfigure(0, weight=0, minsize=settings.uism.TOP_BAR_SIDE__WIDTH) + config_window.grid_rowconfigure(0, weight=0, minsize=settings.uism.TOP_BAR__HEIGHT) + config_window.side_menu_config_window_title_logo_frame = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0) + config_window.side_menu_config_window_title_logo_frame.grid(row=0, column=0, sticky="nsew") + + config_window.side_menu_config_window_title_logo_frame.grid_rowconfigure(0,weight=1) + config_window.side_menu_config_window_title_logo_frame.grid_columnconfigure(0,weight=1) + config_window.side_menu_config_window_title_logo_wrapper = CTkFrame(config_window.side_menu_config_window_title_logo_frame, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0) + config_window.side_menu_config_window_title_logo_wrapper.grid(row=0, column=0, padx=settings.uism.TOP_BAR_SIDE__TITLE_PADX, pady=settings.uism.TOP_BAR__IPADY, sticky="nsew") + + + + + config_window.side_menu_config_window_title_logo_wrapper.grid_rowconfigure(0,weight=1) + config_window.side_menu_config_window_title = CTkLabel( + config_window.side_menu_config_window_title_logo_frame, + text="Settings", + height=0, + anchor="w", + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TOP_BAR_SIDE__CONFIG_TITLE_FONT_SIZE, weight="bold"), + text_color=settings.ctm.LABELS_TEXT_COLOR, + ) + config_window.side_menu_config_window_title.place(relx=0.275, rely=0.5, anchor="w") + + config_window.side_menu_config_window_title_logo = CTkLabel( + config_window.side_menu_config_window_title_logo_frame, + text=None, + height=0, + anchor="w", + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.VRCT_LOGO_MARK),size=settings.uism.TOP_BAR_SIDE__CONFIG_LOGO_MARK_SIZE), + ) + config_window.side_menu_config_window_title_logo.place(relx=0.08, rely=0.59, anchor="w") diff --git a/vrct_gui/config_window/widgets/createSettingBoxTitle.py b/vrct_gui/config_window/widgets/createSettingBoxTitle.py new file mode 100644 index 00000000..57f5c573 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSettingBoxTitle.py @@ -0,0 +1,20 @@ +from customtkinter import CTkFont, CTkFrame, CTkLabel + +def createSettingBoxTitle(config_window, settings): + + config_window.grid_columnconfigure(1, weight=1) + config_window.main_current_active_config_title_container = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0) + config_window.main_current_active_config_title_container.grid(row=0, column=1, sticky="nsew") + + + config_window.main_current_active_config_title_container.grid_rowconfigure(0, weight=1) + config_window.main_current_active_config_title = CTkLabel( + config_window.main_current_active_config_title_container, + height=0, + text=None, + anchor="w", + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TOP_BAR_MAIN__TITLE_FONT_SIZE, weight="bold"), + text_color=settings.ctm.LABELS_TEXT_COLOR + ) + config_window.main_current_active_config_title.grid(row=0, column=0, padx=0, pady=settings.uism.TOP_BAR__IPADY) + diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/__init__.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/__init__.py new file mode 100644 index 00000000..245472c9 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/__init__.py @@ -0,0 +1 @@ +from .createSideMenuAndSettingsBoxContainers import createSideMenuAndSettingsBoxContainers \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/addConfigSideMenuItem.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/addConfigSideMenuItem.py new file mode 100644 index 00000000..1f518a07 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/addConfigSideMenuItem.py @@ -0,0 +1,109 @@ +from customtkinter import CTkFont, CTkFrame, CTkLabel + +from ....ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, switchActiveTabAndPassiveTab, switchTabsColor + + + +def addConfigSideMenuItem(config_window, settings, side_menu_settings, side_menu_row, all_side_menu_tab_attr_name): + + + def switchActiveAndPassiveSettingBoxContainerTabsColor(target_active_widget): + + setting_box_container_tabs = [] + for tab_attr_name in all_side_menu_tab_attr_name: + tab_attr = getattr(config_window, tab_attr_name) + setting_box_container_tabs.append(tab_attr) + + switchTabsColor( + target_widget=target_active_widget, + tab_buttons=setting_box_container_tabs, + active_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR, + active_text_color=settings.ctm.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR, + passive_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR, + passive_text_color=settings.ctm.LABELS_TEXT_COLOR + ) + + for setting_box_container_tab in setting_box_container_tabs: + setting_box_container_tab.children["!ctkframe"].place(relx=-1) + + target_active_widget.children["!ctkframe"].place(relx=0) + + + + + def switchSettingBoxContainerTabFunction(target_active_widget): + switchActiveAndPassiveSettingBoxContainerTabsColor(target_active_widget) + switchActiveTabAndPassiveTab(target_active_widget, config_window.current_active_side_menu_tab, config_window.current_active_side_menu_tab.passive_function, settings.ctm.SIDE_MENU_LABELS_HOVERED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_CLICKED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR) + config_window.current_active_side_menu_tab = target_active_widget + + + + + + + def switchSettingBoxContainer(target_setting_box_container_attr_name): + config_window.current_active_setting_box_container.grid_remove() + config_window.current_active_setting_box_container = getattr(config_window, target_setting_box_container_attr_name) + config_window.current_active_setting_box_container.grid() + + # Move to the top position when the setting box is switched. + config_window.main_setting_box_scrollable_container._parent_canvas.yview_moveto("0") + + + def switchToTargetSettingBoxContainer(e, text, target_active_tab_widget_attr_name, target_setting_box_container_attr_name): + print("switchToTargetSettingBoxContainer", target_setting_box_container_attr_name) + config_window.main_current_active_config_title.configure(text=text) + target_active_tab_widget = getattr(config_window, target_active_tab_widget_attr_name) + switchSettingBoxContainerTabFunction(target_active_tab_widget) + switchSettingBoxContainer(target_setting_box_container_attr_name) + + + + + side_menu_tab_attr_name = side_menu_settings["side_menu_tab_attr_name"] + label_attr_name = side_menu_settings["label_attr_name"] + selected_mark_attr_name = side_menu_settings["selected_mark_attr_name"] + text = side_menu_settings["text"] + setting_box_container_attr_name = side_menu_settings["setting_box_container_settings"]["setting_box_container_attr_name"] + command = lambda e: switchToTargetSettingBoxContainer( + e=e, + text=text, + target_active_tab_widget_attr_name=side_menu_tab_attr_name, + target_setting_box_container_attr_name=setting_box_container_attr_name, + ) + + + # Side menu + frame_widget = CTkFrame(config_window.side_menu_container, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR, cursor="hand2", width=0, height=0) + setattr(config_window, side_menu_tab_attr_name, frame_widget) + + frame_widget.grid(row=side_menu_row, column=0, pady=(0,1), sticky="ew") + frame_widget.grid_columnconfigure(0, weight=1) + + label_widget = CTkLabel( + frame_widget, + text=text, + height=0, + corner_radius=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SIDE_MENU_LABELS_FONT_SIZE, weight="normal"), + anchor="w", + text_color=settings.ctm.LABELS_TEXT_COLOR, + ) + setattr(config_window, label_attr_name, label_widget) + + selected_mark_widget = CTkFrame(frame_widget, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR, width=3, height=0) + setattr(config_window, selected_mark_attr_name, selected_mark_widget) + + + + + + # Arrange + selected_mark_widget.place(relx=-1, rely=0.5, relheight=1, anchor="w") + label_widget.grid(row=0, column=0, padx=settings.uism.SIDE_MENU_LABELS_IPADX, pady=settings.uism.SIDE_MENU_LABELS_IPADY, sticky="ew") + + bindEnterAndLeaveColor([frame_widget, label_widget], settings.ctm.SIDE_MENU_LABELS_HOVERED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR) + bindButtonPressColor([frame_widget, label_widget], settings.ctm.SIDE_MENU_LABELS_CLICKED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR) + + frame_widget.passive_function = command + bindButtonReleaseFunction([frame_widget, label_widget], command) diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSettingBoxContainer.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSettingBoxContainer.py new file mode 100644 index 00000000..7935e7d6 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSettingBoxContainer.py @@ -0,0 +1,61 @@ +from customtkinter import CTkFont, CTkFrame, CTkLabel + + +def createSettingBoxContainer(config_window, settings, setting_box_container_settings): + + + def createSectionTitle(container_widget, section_title): + setting_box_wrapper_section_title_frame = CTkFrame(container_widget, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + + setting_box_wrapper_section_title = CTkLabel( + setting_box_wrapper_section_title_frame, + text=section_title, + anchor="w", + height=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SB__SECTION_TITLE_FONT_SIZE, weight="normal"), + text_color=settings.ctm.LABELS_TEXT_COLOR + ) + setting_box_wrapper_section_title.grid(row=0, column=0, padx=0, pady=settings.uism.SB__SECTION_TITLE_BOTTOM_PADY) + + return setting_box_wrapper_section_title_frame + + # Common setting + + # Setting box container + setting_box_container_widget = CTkFrame(config_window.main_setting_box_bg_wrapper, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + setattr(config_window, setting_box_container_settings["setting_box_container_attr_name"], setting_box_container_widget) + + + + + setting_boxes_length = len(setting_box_container_settings["setting_boxes"]) + setting_box_row = 0 + for i, setting_box_setting in enumerate(setting_box_container_settings["setting_boxes"]): + SB__TOP_PADY = 0 + SB__BOTTOM_PADY = settings.uism.SB__BOTTOM_PADY + + setting_box_and_section_title_wrapper = CTkFrame(setting_box_container_widget, fg_color=settings.ctm.SB__WRAPPER_BG_COLOR, corner_radius=0, width=0, height=0) + + if setting_box_setting["section_title"] is not None: + setting_box_wrapper_section_title_frame= createSectionTitle( + container_widget=setting_box_and_section_title_wrapper, + section_title=setting_box_setting["section_title"], + ) + setting_box_wrapper_section_title_frame.grid(row=0, column=0, sticky="ew", padx=0, pady=0) + if i == 0: SB__TOP_PADY = settings.uism.SB__TOP_PADY_IF_WITH_SECTION_TITLE + + # if the first one of setting boxes, adjust top pady + if i == 0: SB__TOP_PADY = settings.uism.SB__TOP_PADY_IF_WITHOUT_SECTION_TITLE + + # if the last one of setting boxes, remove bottom pady + if i+1 == setting_boxes_length: SB__BOTTOM_PADY = 0 + + setting_box_wrapper = CTkFrame(setting_box_and_section_title_wrapper, fg_color=settings.ctm.SB__WRAPPER_BG_COLOR, corner_radius=0, width=0, height=0) + setting_box_wrapper.grid(row=1, column=0) + setting_box_row+=1 + + setting_box_and_section_title_wrapper.grid(row=setting_box_row, column=0, sticky="ew", padx=0, pady=(SB__TOP_PADY, SB__BOTTOM_PADY)) + + if setting_box_setting["setting_box"] is not None: + setting_box_setting["setting_box"](setting_box_wrapper=setting_box_wrapper, config_window=config_window, settings=settings) + diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSideMenuAndSettingsBoxContainers.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSideMenuAndSettingsBoxContainers.py new file mode 100644 index 00000000..161d5e96 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/createSideMenuAndSettingsBoxContainers.py @@ -0,0 +1,149 @@ +from customtkinter import CTkFrame, CTkScrollableFrame + +from ....ui_utils import setDefaultActiveTab + +from .addConfigSideMenuItem import addConfigSideMenuItem +from .createSettingBoxContainer import createSettingBoxContainer + + +from .setting_box_containers import createSettingBox_General + + +def createSideMenuAndSettingsBoxContainers(config_window, settings): + + # Main container + config_window.main_bg_container = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + config_window.main_bg_container.grid(row=1, column=1, sticky="nsew") + + config_window.main_bg_container.grid_columnconfigure(0, weight=1) + config_window.main_bg_container.grid_rowconfigure(0, weight=0) + + + + + # Side menu Base + config_window.grid_rowconfigure(1, weight=1) + config_window.side_menu_bg_container = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_BG_COLOR, width=0, height=0) + config_window.side_menu_bg_container.grid(row=1, column=0, sticky="nsew") + + + config_window.side_menu_container = CTkFrame(config_window.side_menu_bg_container, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR, width=0, height=0) + config_window.side_menu_container.grid(row=0, column=0, padx=settings.uism.TOP_BAR_SIDE__TITLE_PADX, pady=(settings.uism.SIDE_MENU_TOP_PADY, 0)) + + + + # Setting box container + config_window.main_bg_container.grid_rowconfigure(1, weight=1) + config_window.main_setting_box_scrollable_container = CTkScrollableFrame(config_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR) + config_window.main_setting_box_scrollable_container.grid(row=1, column=0, sticky="nsew") + + + config_window.main_setting_box_bg_wrapper = CTkFrame(config_window.main_setting_box_scrollable_container, corner_radius=0, width=0, height=0, fg_color=settings.ctm.MAIN_BG_COLOR) + config_window.main_setting_box_bg_wrapper.grid(row=0, column=0, pady=settings.uism.SB__BOTTOM_MARGIN, sticky="n") + + + + side_menu_and_setting_box_containers_settings = [ + { + "side_menu_tab_attr_name": "side_menu_tab_general", + "label_attr_name": "label_general", + "selected_mark_attr_name": "translation_selected_mark", + "text": "General", + "setting_box_container_settings": { + "setting_box_container_attr_name": "setting_box_container_general", + "setting_boxes": [ + { "section_title": None, "setting_box": createSettingBox_General }, + # { "section_title": "General Section Title", "setting_box": createSettingBox_General }, + # { "section_title": None, "setting_box": createSettingBox_General }, + ] + }, + "activate_by_default": True, + }, + { + "side_menu_tab_attr_name": "side_menu_tab_translation", + "label_attr_name": "label_translation", + "selected_mark_attr_name": "transcription_send_selected_mark", + "text": "Translation", + "setting_box_container_settings": { + "setting_box_container_attr_name": "setting_box_container_translation", + "setting_boxes": [ + { "section_title": None, "setting_box": None }, + ] + }, + }, + { + "side_menu_tab_attr_name": "side_menu_tab_transcription", + "label_attr_name": "label_transcription", + "selected_mark_attr_name": "transcription_receive_selected_mark", + "text": "Transcription", + "setting_box_container_settings": { + "setting_box_container_attr_name": "setting_box_container_transcription", + "setting_boxes": [ + { "section_title": None, "setting_box": None }, + ] + }, + }, + { + "side_menu_tab_attr_name": "side_menu_tab_parameters", + "label_attr_name": "label_parameters", + "selected_mark_attr_name": "foreground_selected_mark", + "text": "Parameters", + "setting_box_container_settings": { + "setting_box_container_attr_name": "setting_box_container_parameters", + "setting_boxes": [ + { "section_title": None, "setting_box": None }, + ] + }, + }, + { + "side_menu_tab_attr_name": "side_menu_tab_others", + "label_attr_name": "label_others", + "selected_mark_attr_name": "foreground_selected_mark", + "text": "Others", + "setting_box_container_settings": { + "setting_box_container_attr_name": "setting_box_container_others", + "setting_boxes": [ + { "section_title": None, "setting_box": None }, + ] + }, + }, + ] + + all_side_menu_tab_attr_name = [item["side_menu_tab_attr_name"] for item in side_menu_and_setting_box_containers_settings] + + side_menu_row=0 + for sm_and_sbc_setting in side_menu_and_setting_box_containers_settings: + addConfigSideMenuItem( + config_window=config_window, + settings=settings, + side_menu_settings=sm_and_sbc_setting, + side_menu_row=side_menu_row, + all_side_menu_tab_attr_name=all_side_menu_tab_attr_name, + ) + side_menu_row+=1 + + + createSettingBoxContainer( + config_window=config_window, + settings=settings, + setting_box_container_settings=sm_and_sbc_setting["setting_box_container_settings"], + + ) + + + if sm_and_sbc_setting.get("activate_by_default", None) is not None: + # Set default active side menu tab + config_window.main_current_active_config_title.configure(text=sm_and_sbc_setting["text"]) + config_window.current_active_side_menu_tab = getattr(config_window, sm_and_sbc_setting["side_menu_tab_attr_name"]) + setDefaultActiveTab( + active_tab_widget=config_window.current_active_side_menu_tab, + active_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR, + active_text_color=settings.ctm.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR + ) + config_window.current_active_side_menu_tab.children["!ctkframe"].place(relx=0) + + # Set default active setting box container + config_window.current_active_setting_box_container = getattr(config_window, sm_and_sbc_setting["setting_box_container_settings"]["setting_box_container_attr_name"]) + config_window.current_active_setting_box_container.grid() + + diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/SettingBoxGenerator.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/SettingBoxGenerator.py new file mode 100644 index 00000000..5e0a530d --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/SettingBoxGenerator.py @@ -0,0 +1,494 @@ +from customtkinter import CTkOptionMenu, CTkFont, CTkFrame, CTkLabel, CTkRadioButton, CTkEntry, CTkSlider, CTkSwitch, CTkCheckBox, CTkProgressBar, END as CTK_END +from ctk_scrollable_dropdown import CTkScrollableDropdown + +from vrct_gui.ui_utils import createButtonWithImage + + + +class SettingBoxGenerator(): + def __init__(self, config_window, settings): + + self.IS_CONFIG_WINDOW_COMPACT_MODE = settings.IS_CONFIG_WINDOW_COMPACT_MODE + self.ctm = settings.ctm + self.uism = settings.uism + self.FONT_FAMILY = settings.FONT_FAMILY + self.config_window = config_window + + + + def _createSettingBoxFrameWrapper(self, setting_box_frame): + setting_box_frame_wrapper = CTkFrame(setting_box_frame, corner_radius=0, fg_color=self.ctm.SB__BG_COLOR, width=self.uism.SB__MAIN_WIDTH, height=0) + setting_box_frame_wrapper.grid(row=0, column=0, padx=self.uism.SB__IPADX, pady=self.uism.SB__IPADY, sticky="ew") + setting_box_frame_wrapper.grid_columnconfigure((0,1), weight=1, minsize=int(self.uism.SB__MAIN_WIDTH / 2)) + return setting_box_frame_wrapper + + def _createSettingBoxFrame(self, parent_widget, label_text, desc_text): + setting_box_frame = CTkFrame(parent_widget, corner_radius=0, fg_color=self.ctm.SB__BG_COLOR, width=0, height=0) + setting_box_frame_wrapper = self._createSettingBoxFrameWrapper(setting_box_frame) + self._setSettingBoxLabels(setting_box_frame_wrapper, label_text, desc_text) + + # "pady=(0,1)" is for bottom padding. It can be removed(override) when you do like "self.attr_name.grid(row=row, pady=0)" + setting_box_frame.grid(column=0, padx=0, pady=(0,1), sticky="ew") + return (setting_box_frame, setting_box_frame_wrapper) + + def _setSettingBoxLabels(self, setting_box_frame, label_text, desc_text=False): + + setting_box_labels_frame = CTkFrame(setting_box_frame, corner_radius=0, fg_color=self.ctm.SB__BG_COLOR, width=0, height=0) + + setting_box_label = CTkLabel( + setting_box_labels_frame, + text=label_text, + anchor="w", + # height=0, + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__LABEL_FONT_SIZE, weight="normal"), + text_color=self.ctm.LABELS_TEXT_COLOR + ) + setting_box_label.grid(row=0, column=0, padx=0, pady=0, sticky="ew") + + if desc_text == False or self.IS_CONFIG_WINDOW_COMPACT_MODE is True: + pass + else: + self.setting_box_desc = CTkLabel( + setting_box_labels_frame, + text=desc_text, + anchor="w", + justify="left", + # height=0, + wraplength=int(self.uism.SB__MAIN_WIDTH / 2), + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__DESC_FONT_SIZE, weight="normal"), + text_color=self.ctm.LABELS_DESC_TEXT_COLOR + ) + self.setting_box_desc.grid(row=1, column=0, padx=0, pady=(self.uism.SB__DESC_TOP_PADY,0), sticky="ew") + + setting_box_labels_frame.grid(row=0, column=0, padx=0, pady=0, sticky="w") + + + + def createSettingBoxDropdownMenu(self, parent_widget, label_text, desc_text, optionmenu_attr_name, dropdown_menu_attr_name, dropdown_menu_values, command, variable): + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_dropdown_menu_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_dropdown_menu_frame.grid(row=0, column=1, padx=0, sticky="e") + + self.createOption_DropdownMenu( + setting_box_dropdown_menu_frame=setting_box_dropdown_menu_frame, + optionmenu_attr_name=optionmenu_attr_name, + dropdown_menu_attr_name=dropdown_menu_attr_name, + dropdown_menu_values=dropdown_menu_values, + command=command, + variable=variable, + ) + + return setting_box_frame + + + + + def createSettingBoxSwitch(self, parent_widget, label_text, desc_text, switch_attr_name, is_checked, command): + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_switch_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_switch_frame.grid(row=0, column=1, padx=0, sticky="e") + + switch_widget = CTkSwitch( + setting_box_switch_frame, + text=None, + height=0, + width=0, + corner_radius=int(self.uism.SB__SWITCH_BOX_HEIGHT/2), + border_width=0, + switch_height=self.uism.SB__SWITCH_BOX_HEIGHT, + switch_width=self.uism.SB__SWITCH_BOX_WIDTH, + onvalue=True, + offvalue=False, + command=command, + fg_color=self.ctm.SB__SWITCH_BOX_BG_COLOR, + # bg_color="red", + progress_color=self.ctm.SB__SWITCH_BOX_ACTIVE_BG_COLOR, + ) + setattr(self.config_window, switch_attr_name, switch_widget) + + switch_widget.select() if is_checked else switch_widget.deselect() + + switch_widget.grid(row=0, column=0) + + return setting_box_frame + + + + def createSettingBoxCheckbox(self, parent_widget, label_text, desc_text, checkbox_attr_name, is_checked, command): + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_checkbox_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_checkbox_frame.grid(row=0, column=1, padx=0, sticky="e") + + checkbox_widget = CTkCheckBox( + setting_box_checkbox_frame, + text=None, + width=0, + checkbox_width=self.uism.SB__CHECKBOX_SIZE, + checkbox_height=self.uism.SB__CHECKBOX_SIZE, + onvalue=True, + offvalue=False, + command=command, + corner_radius=self.uism.SB__CHECKBOX_CORNER_RADIUS, + border_width=self.uism.SB__CHECKBOX_BORDER_WIDTH, + border_color=self.ctm.SB__CHECKBOX_BORDER_COLOR, + hover_color=self.ctm.SB__CHECKBOX_HOVER_COLOR, + checkmark_color=self.ctm.SB__CHECKBOX_CHECKMARK_COLOR, + fg_color=self.ctm.SB__CHECKBOX_CHECKED_COLOR, + # fg_color=self.ctm.SB__SWITCH_BOX_BG_COLOR, + # bg_color="red", + # progress_color=self.ctm.SB__SWITCH_BOX_ACTIVE_BG_COLOR, + ) + setattr(self.config_window, checkbox_attr_name, checkbox_widget) + + checkbox_widget.select() if is_checked else checkbox_widget.deselect() + + checkbox_widget.grid(row=0, column=0) + + return setting_box_frame + + + + + + + def createSettingBoxSlider(self, parent_widget, label_text, desc_text, slider_attr_name, slider_range, slider_number_of_steps, command, variable): + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_slider_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_slider_frame.grid(row=0, column=1, padx=0, sticky="e") + + slider_widget = CTkSlider( + setting_box_slider_frame, + from_=slider_range[0], + to=slider_range[1], + number_of_steps=slider_number_of_steps, + button_color=self.ctm.SB__SLIDER_BUTTON_COLOR, + button_hover_color=self.ctm.SB__SLIDER_BUTTON_HOVERED_COLOR, + command=command, + variable=variable, + ) + setattr(self.config_window, slider_attr_name, slider_widget) + + slider_widget.grid(row=0, column=0) + + return setting_box_frame + + + + + def createSettingBoxProgressbarXSlider(self, + parent_widget, label_text, desc_text, command, + entry_attr_name, + slider_attr_name, slider_range, slider_number_of_steps, + progressbar_attr_name, + passive_button_attr_name, passive_button_command, + active_button_attr_name, active_button_command, + button_image_filename, + variable, + ): + + + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_progressbar_x_slider_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_progressbar_x_slider_frame.grid(row=0, column=1, padx=0, sticky="e") + + + ENTRY_WIDTH = self.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_WIDTH + BAR_WIDTH = self.uism.SB__PROGRESSBAR_X_SLIDER__BAR_WIDTH + + BAR_PADDING = int(ENTRY_WIDTH + self.uism.SB__PROGRESSBAR_X_SLIDER__BAR_RIGHT_PADX) + BUTTON_PADDING = int(BAR_WIDTH + BAR_PADDING + self.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_RIGHT_PADX) + + def adjusted_command__for_entry_bind__Any_KeyRelease(e): + # try: + # int(e.widget.get()) + # except: + # e.widget.delete(0, CTK_END) + # return + # print(int(e.widget.get())) + + + i = int(e.widget.get()) + if i < 0 or i > slider_range[1]: + e.widget.delete(0, CTK_END) + i = max(0, min(int(e.widget.get()), slider_range[1])) + # e.widget.insert(0, i) + command(i) + def adjusted_command__for_slider(value): + command(int(value)) + + entry_widget = CTkEntry( + setting_box_progressbar_x_slider_frame, + width=ENTRY_WIDTH, + height=self.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT, + textvariable=variable, + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__ENTRY_FONT_SIZE, weight="normal"), + ) + + entry_widget.bind("", adjusted_command__for_entry_bind__Any_KeyRelease) + entry_widget.grid(row=0, column=0, padx=0, pady=0, sticky="e") + setattr(self.config_window, entry_attr_name, entry_widget) + + + # at least 2px is needed otherwise the slider button is gonna broken. + SLIDER_BORDER_WIDTH = max(2,self.uism.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_LENGTH) + SLIDER_BUTTON_LENGTH = int(SLIDER_BORDER_WIDTH/2) + slider_widget = CTkSlider( + setting_box_progressbar_x_slider_frame, + from_=slider_range[0], + to=slider_range[1], + number_of_steps=slider_number_of_steps, + command=adjusted_command__for_slider, + variable=variable, + height=self.uism.SB__PROGRESSBAR_X_SLIDER__SLIDER_HEIGHT, + width=BAR_WIDTH, + border_width=0, + button_length=SLIDER_BORDER_WIDTH, + button_corner_radius=SLIDER_BUTTON_LENGTH, + corner_radius=0, + button_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR, + button_hover_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR, + fg_color=self.ctm.SB__BG_COLOR, + progress_color=self.ctm.SB__BG_COLOR, + border_color=self.ctm.SB__BG_COLOR, + ) + slider_widget.grid(row=0, column=0, padx=(0, BAR_PADDING), sticky="e") + setattr(self.config_window, slider_attr_name, slider_widget) + + + + + progressbar_widget = CTkProgressBar( + setting_box_progressbar_x_slider_frame, + width=BAR_WIDTH, + height=self.uism.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_HEIGHT, + corner_radius=0, + ) + setattr(self.config_window, progressbar_attr_name, progressbar_widget) + progressbar_widget.grid(row=0, column=0, padx=(0, BAR_PADDING), sticky="e") + progressbar_widget.set(0) + + + + + passive_button_wrapper = self._createPassiveButtonForProgressbarXSlider(setting_box_progressbar_x_slider_frame, BUTTON_PADDING, passive_button_command, button_image_filename) + setattr(self.config_window, passive_button_attr_name, passive_button_wrapper) + + active_button_wrapper = self._createActiveButtonForProgressbarXSlider(setting_box_progressbar_x_slider_frame, BUTTON_PADDING, active_button_command, button_image_filename) + setattr(self.config_window, active_button_attr_name, active_button_wrapper) + + passive_button_wrapper.grid() + return setting_box_frame + + + + + def createSettingBoxEntry(self, parent_widget, label_text, desc_text, entry_attr_name, entry_width, entry_bind__Any_KeyRelease, entry_textvariable): + (setting_box_frame, setting_box_frame_wrapper) = self._createSettingBoxFrame(parent_widget, label_text, desc_text) + + setting_box_entry_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.ctm.SB__BG_COLOR) + setting_box_entry_frame.grid(row=0, column=1, padx=0, sticky="e") + + entry_widget = CTkEntry( + setting_box_entry_frame, + width=entry_width, + height=self.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT, + textvariable=entry_textvariable, + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__ENTRY_FONT_SIZE, weight="normal"), + ) + entry_widget.bind("", entry_bind__Any_KeyRelease) + setattr(self.config_window, entry_attr_name, entry_widget) + + + entry_widget.grid(row=0, column=0) + + return setting_box_frame + + + + # if setting_box_type == "dropdown_menu_x_dropdown_menu": + # self.setting_box_dropdown_menu_x_dropdown_menu = CTkFrame(self.setting_box, corner_radius=0, fg_color=self.ctm.SB__BG_COLOR, width=0, height=0) + # self.setting_box_dropdown_menu_x_dropdown_menu.grid(row=0, column=1, padx=(0, self.uism.SB__RIGHT_PADX), rowspan=2, sticky="e") + + + + # # Labels + # self.optionmenu_label_left = CTkLabel( + # self.setting_box_dropdown_menu_x_dropdown_menu, + # text=kwargs["left_dropdown_menu_label"], + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"), + # ) + # self.optionmenu_label_left.grid(row=0, column=0) + + # self.the_space_between_optionmenu = CTkLabel( + # self.setting_box_dropdown_menu_x_dropdown_menu, + # text=None, + # ) + # self.the_space_between_optionmenu.grid(row=0, column=1) + + + # self.optionmenu_label_right = CTkLabel( + # self.setting_box_dropdown_menu_x_dropdown_menu, + # text=kwargs["right_dropdown_menu_label"], + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"), + # ) + # self.optionmenu_label_right.grid(row=0, column=2) + + + + # # Option menus + # self.createOption_DropdownMenu( + # setattr_obj, + # self.setting_box_dropdown_menu_x_dropdown_menu, + # kwargs["left_optionmenu_attr_name"], + # kwargs["left_dropdown_menu_attr_name"], + # dropdown_menu_values=kwargs["left_dropdown_menu_values"], + # width=150, + # command=kwargs["left_dropdown_menu_command"], + # variable=kwargs["left_dropdown_menu_variable"], + # ) + # getattr(setattr_obj, kwargs["left_optionmenu_attr_name"]).grid(row=1, column=0) + + + + # self.the_label_between_optionmenu = CTkLabel( + # self.setting_box_dropdown_menu_x_dropdown_menu, + # text="-->", + # # anchor="w", + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"), + # text_color=self.ctm.LABELS_TEXT_COLOR + # ) + # self.the_label_between_optionmenu.grid(row=1, column=1, padx=self.uism.SB__RIGHT_PADX/2) + + + # self.createOption_DropdownMenu( + # setattr_obj, + # self.setting_box_dropdown_menu_x_dropdown_menu, + # kwargs["right_optionmenu_attr_name"], + # kwargs["right_dropdown_menu_attr_name"], + # dropdown_menu_values=kwargs["right_dropdown_menu_values"], + # width=150, + # command=kwargs["right_dropdown_menu_command"], + # variable=kwargs["right_dropdown_menu_variable"], + # ) + # getattr(setattr_obj, kwargs["right_optionmenu_attr_name"]).grid(row=1, column=2) + + + + + # if setting_box_type == "radio_buttons": + # self.setting_box_radio_buttons_frame = CTkFrame(self.setting_box, corner_radius=0, width=0, height=0) + # self.setting_box_radio_buttons_frame.grid(row=0, column=1, padx=(0, self.uism.SB__RIGHT_PADX), rowspan=2, sticky="e") + + # RADIO_BUTTON_RIGHT_PAD = 14 + # self.setting_box_radio_button_1 = CTkRadioButton( + # self.setting_box_radio_buttons_frame, + # text="lorem ipsum", + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal") + # ) + # self.setting_box_radio_button_1.grid(row=0, column=0, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e") + + # self.setting_box_radio_button_2 = CTkRadioButton( + # self.setting_box_radio_buttons_frame, + # text="lorem ipsum", + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal") + # ) + # self.setting_box_radio_button_2.grid(row=0, column=1, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e") + + # self.setting_box_radio_button_3 = CTkRadioButton( + # self.setting_box_radio_buttons_frame, + # text="lorem ipsum", + # font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal") + # ) + # self.setting_box_radio_button_3.grid(row=0, column=2, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e") + + + + + + def createOption_DropdownMenu(self, setting_box_dropdown_menu_frame, optionmenu_attr_name, dropdown_menu_attr_name, dropdown_menu_values, command, variable): + option_menu_widget = CTkOptionMenu( + setting_box_dropdown_menu_frame, + height=self.uism.SB__OPTIONMENU_HEIGHT, + width=self.uism.SB__OPTIONMENU_WIDTH, + button_color=self.ctm.SB__OPTIONMENU_BG_COLOR, + button_hover_color=self.ctm.SB__OPTIONMENU_HOVERED_BG_COLOR, + fg_color=self.ctm.SB__OPTIONMENU_BG_COLOR, + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"), + variable=variable, + anchor="w", + ) + option_menu_widget.grid(row=0, column=0, sticky="e") + setattr(self.config_window, optionmenu_attr_name, option_menu_widget) + + # set the value to the option menu's variable automatically + def adjustedCommand(selected_value): + option_menu_widget.set(selected_value) + command(selected_value) + + dropdown_menu_widget = CTkScrollableDropdown( + option_menu_widget, + values=dropdown_menu_values, + justify="left", + width=self.uism.SB__DROPDOWN_MENU_WIDTH, + min_show_button_num=6, + button_pady=0, + frame_corner_radius=self.uism.SB__DROPDOWN_MENU_FRAME_CORNER_RADIUS, + max_button_height=self.uism.SB__DROPDOWN_MENU_MAX_BUTTON_HEIGHT, + max_height=self.uism.SB__DROPDOWN_MENU_FRAME_MAX_HEIGHT, + font=CTkFont(family=self.FONT_FAMILY, size=self.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"), + command=adjustedCommand, + ) + + # dropdown_menu_widget.bind( + # "", + # lambda e: dropdown_menu_widget._withdraw() if not str(e.widget).startswith(str(dropdown_menu_widget.frame._parent_frame)) else None, + # ) + dropdown_menu_widget.bind( + "", + lambda e: print(e), + ) + + setattr(self.config_window, dropdown_menu_attr_name, dropdown_menu_widget) + return option_menu_widget + + + + + def _createPassiveButtonForProgressbarXSlider(self, setting_box_progressbar_x_slider_frame, BUTTON_PADDING, button_command, button_image_filename): + button_wrapper = createButtonWithImage( + parent_widget=setting_box_progressbar_x_slider_frame, + button_fg_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR, + button_enter_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR, + button_clicked_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR, + button_image_filename=button_image_filename, + button_image_size=self.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE, + button_ipadxy=self.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY, + button_command=button_command, + shape="circle", + ) + button_wrapper.grid(row=0, column=0, padx=(0,BUTTON_PADDING), sticky="e") + button_wrapper.grid_remove() + return button_wrapper + + + + def _createActiveButtonForProgressbarXSlider(self, setting_box_progressbar_x_slider_frame, BUTTON_PADDING, button_command, button_image_filename): + button_wrapper = createButtonWithImage( + parent_widget=setting_box_progressbar_x_slider_frame, + button_fg_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR, + button_enter_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR, + button_clicked_color=self.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR, + button_image_filename=button_image_filename, + button_image_size=self.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE, + button_ipadxy=self.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY, + button_command=button_command, + shape="circle", + ) + button_wrapper.grid(row=0, column=0, padx=(0,BUTTON_PADDING), sticky="e") + button_wrapper.grid_remove() + return button_wrapper \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/__init__.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/__init__.py new file mode 100644 index 00000000..f992f8c0 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/__init__.py @@ -0,0 +1 @@ +from .setting_box_general import createSettingBox_General \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/__init__.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/__init__.py new file mode 100644 index 00000000..c0c243b9 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/__init__.py @@ -0,0 +1 @@ +from .createSettingBox_General import createSettingBox_General \ No newline at end of file diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/createSettingBox_General.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/createSettingBox_General.py new file mode 100644 index 00000000..70fd7bd3 --- /dev/null +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_general/createSettingBox_General.py @@ -0,0 +1,225 @@ +from time import sleep + +from customtkinter import StringVar, IntVar + + +from ..SettingBoxGenerator import SettingBoxGenerator + +from config import config + +def createSettingBox_General(setting_box_wrapper, config_window, settings): + + + sbg = SettingBoxGenerator(config_window, settings) + + createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu + createSettingBoxSwitch = sbg.createSettingBoxSwitch + createSettingBoxCheckbox = sbg.createSettingBoxCheckbox + createSettingBoxSlider = sbg.createSettingBoxSlider + createSettingBoxProgressbarXSlider = sbg.createSettingBoxProgressbarXSlider + createSettingBoxEntry = sbg.createSettingBoxEntry + + + + def checkbox_input_speaker_threshold_check_callback(e, passive_button_wrapper_widget, active_button_wrapper_widget, is_turned_on): + print("is_turned_on", is_turned_on) + + if is_turned_on is True: + passive_button_widget = passive_button_wrapper_widget.children["!ctklabel"] + passive_button_wrapper_widget.configure(fg_color=settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR) + passive_button_widget.configure(fg_color=settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR) + passive_button_wrapper_widget.update_idletasks() + sleep(1) + + passive_button_wrapper_widget.grid_remove() + active_button_wrapper_widget.grid() + + elif is_turned_on is False: + # active_button_widget = active_button_wrapper_widget.children["!ctklabel"] + # active_button_wrapper_widget.configure(fg_color=settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR) + # active_button_widget.configure(fg_color=settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR) + # active_button_wrapper_widget.update_idletasks() + # sleep(3) + + active_button_wrapper_widget.grid_remove() + passive_button_wrapper_widget.grid() + + # def slider_input_speaker_energy_threshold_callback(self, value): + # config_window.INPUT_SPEAKER_ENERGY_THRESHOLD = int(value) + + def set_input_threshold(value): + print(value) + config.INPUT_SPEAKER_ENERGY_THRESHOLD = value + print(config.INPUT_SPEAKER_ENERGY_THRESHOLD) + + + + + + + + + + def dropdownMenuFun(selected_value, optionmenu_widget, dropdown_menu_widget): + print(selected_value) + config.INPUT_SOURCE_LANG = selected_value + + def switchFun(_, switch_box_widget): + print(switch_box_widget.get()) + + def checkboxFun(_, checkbox_box_widget): + print(checkbox_box_widget.get()) + + def sliderFun(_, value, slider_widget): + print(value) + + def entryFun(e, entry_widget): + print(e.widget.get()) + config_window.INPUT_MIC_PHRASE_TIMEOUT = int(e.widget.get()) + print(config_window.INPUT_MIC_PHRASE_TIMEOUT) + + + + row=0 + config_window.sb__dropdown_menu_1 = createSettingBoxDropdownMenu( + parent_widget=setting_box_wrapper, + label_text="Option Menu", + desc_text="Select your preferences from the options menu.\nYou can choose your preferred language.", + optionmenu_attr_name="optionmenu_attr_name_1", + dropdown_menu_attr_name="dropdown_menu_attr_name_1", + dropdown_menu_values=["tt", "Japanese", "English"], + command=lambda value: dropdownMenuFun(value, config_window.optionmenu_attr_name_1, config_window.dropdown_menu_attr_name_1), + variable=StringVar(value=config.INPUT_SOURCE_LANG) + ) + config_window.sb__dropdown_menu_1.grid(row=row) + row+=1 + + + config_window.sb__dropdown_menu_2 = createSettingBoxDropdownMenu( + parent_widget=setting_box_wrapper, + label_text="Option Menu", + desc_text="Select your preferences from the options menu.\nYou can choose your preferred language.", + optionmenu_attr_name="optionmenu_attr_name_2", + dropdown_menu_attr_name="dropdown_menu_attr_name_1", + dropdown_menu_values=["tt", "Japanese", "English"], + command=lambda value: dropdownMenuFun(value, config_window.optionmenu_attr_name_2, config_window.dropdown_menu_attr_name_1), + variable=StringVar(value=config.INPUT_SOURCE_LANG) + ) + config_window.sb__dropdown_menu_2.grid(row=row) + row+=1 + + config_window.sb__switch_1 = createSettingBoxSwitch( + parent_widget=setting_box_wrapper, + label_text="Switch", + desc_text="Turning this switch on will bring happiness.\nAs for turning it off... I leave that to your imagination", + switch_attr_name="switch_attr_name_1", + command=lambda: switchFun(config_window.switch_attr_name_1), + is_checked=True, + ) + config_window.sb__switch_1.grid(row=row) + row+=1 + + config_window.sb__checkbox_1 = createSettingBoxCheckbox( + parent_widget=setting_box_wrapper, + label_text="Checkbox", + desc_text="Checkbox ticked, a checkmark.", + checkbox_attr_name="checkbox_attr_name_1", + command=lambda: checkboxFun(config_window.checkbox_attr_name_1), + is_checked=False, + ) + config_window.sb__checkbox_1.grid(row=row) + row+=1 + + config_window.sb__slider_1 = createSettingBoxSlider( + parent_widget=setting_box_wrapper, + label_text="Slider", + desc_text="Adjust using the slider; the balance is up to you.", + slider_attr_name="slider_attr_name_1", + slider_range=(0, config_window.MAX_SPEAKER_ENERGY_THRESHOLD), + slider_number_of_steps=config_window.MAX_SPEAKER_ENERGY_THRESHOLD, + command=lambda value: sliderFun(value, config_window.slider_attr_name_1), + variable=IntVar(value=config_window.INPUT_SPEAKER_ENERGY_THRESHOLD), + ) + config_window.sb__slider_1.grid(row=row) + row+=1 + + + config_window.sb__progressbar_x_slider_1 = createSettingBoxProgressbarXSlider( + parent_widget=setting_box_wrapper, + label_text="Progressbar and Slider for check the threshold", + desc_text="just the slider to modify the threshold for activating voice input.\nPress the microphone button to start input, and you can adjust it while monitoring the actual volume.", + command=set_input_threshold, # ? + variable=IntVar(value=config.INPUT_MIC_ENERGY_THRESHOLD), + entry_attr_name="progressbar_x_slider__entry_attr_name_1", + + + slider_attr_name="progressbar_x_slider__slider_attr_name_1", + slider_range=(0, config_window.MAX_SPEAKER_ENERGY_THRESHOLD), + slider_number_of_steps=config_window.MAX_SPEAKER_ENERGY_THRESHOLD, + + progressbar_attr_name="progressbar_x_slider__progressbar_attr_name_1", + + passive_button_attr_name="progressbar_x_slider__passive_button_attr_name_1", + passive_button_command=lambda e: checkbox_input_speaker_threshold_check_callback( + e, + config_window.progressbar_x_slider__passive_button_attr_name_1, + config_window.progressbar_x_slider__active_button_attr_name_1, + is_turned_on=True, + ), + active_button_attr_name="progressbar_x_slider__active_button_attr_name_1", + active_button_command=lambda e: checkbox_input_speaker_threshold_check_callback( + e, + config_window.progressbar_x_slider__passive_button_attr_name_1, + config_window.progressbar_x_slider__active_button_attr_name_1, + is_turned_on=False, + ), + button_image_filename="mic_icon_white.png" + ) + config_window.sb__progressbar_x_slider_1.grid(row=row) + row+=1 + + config_window.sb__progressbar_x_slider_2 = createSettingBoxProgressbarXSlider( + parent_widget=setting_box_wrapper, + label_text="Progressbar and Slider for check the threshold2", + desc_text="just the slider to modify the threshold for activating voice input.\nPress the microphone button to start input, and you can adjust it while monitoring the actual volume.", + command=set_input_threshold, # ? + variable=IntVar(value=config.INPUT_SPEAKER_ENERGY_THRESHOLD), + + entry_attr_name="progressbar_x_slider__entry_attr_name_2", + + + slider_attr_name="progressbar_x_slider__slider_attr_name_2", + slider_range=(0, config_window.MAX_SPEAKER_ENERGY_THRESHOLD), + slider_number_of_steps=config_window.MAX_SPEAKER_ENERGY_THRESHOLD, + progressbar_attr_name="progressbar_x_slider__progressbar_attr_name_2", + + passive_button_attr_name="progressbar_x_slider__passive_button_attr_name_2", + passive_button_command=lambda e: checkbox_input_speaker_threshold_check_callback( + e, + config_window.progressbar_x_slider__passive_button_attr_name_2, + config_window.progressbar_x_slider__active_button_attr_name_2, + is_turned_on=True, + ), + active_button_attr_name="progressbar_x_slider__active_button_attr_name_2", + active_button_command=lambda e: checkbox_input_speaker_threshold_check_callback( + e, + config_window.progressbar_x_slider__passive_button_attr_name_2, + config_window.progressbar_x_slider__active_button_attr_name_2, + is_turned_on=False, + ), + button_image_filename="headphones_icon_white.png" + ) + config_window.sb__progressbar_x_slider_2.grid(row=row) + row+=1 + + config_window.sb__entry_1 = createSettingBoxEntry( + parent_widget=setting_box_wrapper, + label_text="Entry", + desc_text="Please input a numerical value.", + entry_attr_name="entry_attr_name_1", + entry_width=settings.uism.SB__ENTRY_WIDTH_100, + entry_bind__Any_KeyRelease=lambda value: entryFun(value, config_window.entry_attr_name_1), + entry_textvariable=IntVar(value=config_window.INPUT_MIC_PHRASE_TIMEOUT), + ) + config_window.sb__entry_1.grid(row=row, pady=0) + row+=1 \ No newline at end of file diff --git a/vrct_gui/main_window/__init__.py b/vrct_gui/main_window/__init__.py new file mode 100644 index 00000000..a34b6566 --- /dev/null +++ b/vrct_gui/main_window/__init__.py @@ -0,0 +1 @@ +from .createMainWindowWidgets import createMainWindowWidgets \ No newline at end of file diff --git a/vrct_gui/main_window/createMainWindowWidgets.py b/vrct_gui/main_window/createMainWindowWidgets.py new file mode 100644 index 00000000..980a15be --- /dev/null +++ b/vrct_gui/main_window/createMainWindowWidgets.py @@ -0,0 +1,93 @@ +from .widgets import createSidebar, createMinimizeSidebarButton, createTextbox, createEntryMessageBox + +from customtkinter import CTkFrame + +from ..ui_utils import createButtonWithImage, getImagePath + + +def createMainWindowWidgets(vrct_gui, settings): + vrct_gui.protocol("WM_DELETE_WINDOW", vrct_gui.quitVRCT) + + # self.IS_DEVELOPER_MODE = False + # self.IS_DEVELOPER_MODE = True + + + + + # self.YOUR_LANGUAGE = "Japanese\n(Japan)" + # self.TARGET_LANGUAGE = "English\n(United States)" + + vrct_gui.iconbitmap(getImagePath("app.ico")) + vrct_gui.title("VRCT") + vrct_gui.geometry(f"{880}x{640}") + vrct_gui.minsize(400, 175) + + + # Main Container + vrct_gui.grid_columnconfigure(1, weight=1) + + vrct_gui.configure(fg_color="#ff7f50") + # return + + + # Main Container + vrct_gui.main_bg_container = CTkFrame(vrct_gui, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + vrct_gui.main_bg_container.grid(row=0, column=1, sticky="nsew") + + + # top bar + vrct_gui.main_bg_container.grid_columnconfigure(0, weight=1) + vrct_gui.main_topbar_container = CTkFrame(vrct_gui.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + vrct_gui.main_topbar_container.grid(row=0, column=0, sticky="ew") + + + + + + vrct_gui.main_topbar_container.columnconfigure(1,weight=1) + vrct_gui.main_topbar_center_container = CTkFrame(vrct_gui.main_topbar_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + vrct_gui.main_topbar_center_container.grid(row=0, column=1, sticky="nsew") + + + + + # Help and Info button + vrct_gui.help_and_info_button_container = createButtonWithImage( + parent_widget=vrct_gui.main_topbar_container, + button_fg_color=settings.ctm.HELP_AND_INFO_BUTTON_BG_COLOR, + button_enter_color=settings.ctm.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR, + button_clicked_color=settings.ctm.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR, + button_image_filename=settings.image_filename.HELP_ICON, + button_image_size=settings.uism.HELP_AND_INFO_BUTTON_SIZE, + button_ipadxy=settings.uism.HELP_AND_INFO_BUTTON_IPADXY, + button_command=vrct_gui.openHelpAndInfoWindow, + corner_radius=settings.uism.HELP_AND_INFO_BUTTON_CORNER_RADIUS, + ) + vrct_gui.help_and_info_button_container.grid(row=0, column=3, padx=settings.uism.HELP_AND_INFO_BUTTON_PADX, pady=settings.uism.HELP_AND_INFO_BUTTON_PADY, sticky="e") + + createSidebar(settings, vrct_gui) + + createMinimizeSidebarButton(settings, vrct_gui) + + createTextbox(settings, vrct_gui) + + createEntryMessageBox(settings, vrct_gui) + + + + + + # def delete_window(self): + # self.vrct_gui.quit() + # self.vrct_gui.destroy() + + # def openConfigWindow(self, e): + # self.config_window.deiconify() + # self.config_window.focus_set() + # self.config_window.focus() + # self.config_window.grab_set() + + # def openHelpAndInfoWindow(self, e): + # self.information_window.deiconify() + # self.information_window.focus_set() + # self.information_window.focus() \ No newline at end of file diff --git a/vrct_gui/main_window/widgets/__init__.py b/vrct_gui/main_window/widgets/__init__.py new file mode 100644 index 00000000..ac037cb8 --- /dev/null +++ b/vrct_gui/main_window/widgets/__init__.py @@ -0,0 +1,4 @@ +from .create_sidebar import createSidebar +from .create_minimize_sidebar_button import createMinimizeSidebarButton +from .create_textbox import createTextbox +from .create_entry_message_box import createEntryMessageBox diff --git a/vrct_gui/main_window/widgets/create_entry_message_box.py b/vrct_gui/main_window/widgets/create_entry_message_box.py new file mode 100644 index 00000000..61dfe593 --- /dev/null +++ b/vrct_gui/main_window/widgets/create_entry_message_box.py @@ -0,0 +1,21 @@ + +from customtkinter import CTkFont, CTkFrame, CTkEntry + +def createEntryMessageBox(settings, main_window): + main_window.main_entry_message_container = CTkFrame(main_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + main_window.main_entry_message_container.grid(row=2, column=0, sticky="ew") + + + main_window.main_entry_message_container.columnconfigure(0, weight=1) + main_window.entry_message_box = CTkEntry( + main_window.main_entry_message_container, + border_color=settings.ctm.TEXTBOX_ENTRY_BORDER_COLOR, + fg_color=settings.ctm.TEXTBOX_ENTRY_BG_COLOR, + text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_COLOR, + placeholder_text="Enter your message...", + placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_COLOR, + height=settings.uism.TEXTBOX_ENTRY_HEIGHT, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_ENTRY_FONT_SIZE, weight="normal"), + ) + main_window.entry_message_box.grid(row=0, column=0, padx=settings.uism.TEXTBOX_ENTRY_PADX, pady=settings.uism.TEXTBOX_ENTRY_PADY, sticky="nsew") + main_window.entry_message_box._entry.grid(padx=settings.uism.TEXTBOX_ENTRY_IPADX, pady=settings.uism.TEXTBOX_ENTRY_IPADY) diff --git a/vrct_gui/main_window/widgets/create_minimize_sidebar_button.py b/vrct_gui/main_window/widgets/create_minimize_sidebar_button.py new file mode 100644 index 00000000..97414c70 --- /dev/null +++ b/vrct_gui/main_window/widgets/create_minimize_sidebar_button.py @@ -0,0 +1,58 @@ + +from customtkinter import CTkFrame, CTkLabel, CTkImage + +from ...ui_utils import getImageFileFromUiUtils, bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction + +from .create_sidebar import createSidebar + + +def createMinimizeSidebarButton(settings, main_window): + + def enableCompactMode(e): + settings.IS_SIDEBAR_COMPACT_MODE = True + main_window.minimize_sidebar_button_container.destroy() + createMinimizeSidebarButton(settings, main_window) + main_window.sidebar_bg_container.destroy() + createSidebar(settings, main_window) + + def disableCompactMode(e): + settings.IS_SIDEBAR_COMPACT_MODE = False + main_window.minimize_sidebar_button_container.destroy() + createMinimizeSidebarButton(settings, main_window) + main_window.sidebar_bg_container.destroy() + createSidebar(settings, main_window) + + + main_window.minimize_sidebar_button_container = CTkFrame(main_window.main_topbar_container, corner_radius=0, fg_color=settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR, cursor="hand2", width=0, height=0) + + + + main_window.minimize_sidebar_button = CTkLabel( + main_window.minimize_sidebar_button_container, + text=None, + corner_radius=0, + height=0, + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT),size=(settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X,settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y)) + ) + + + if settings.IS_SIDEBAR_COMPACT_MODE is True: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT).rotate(180),size=(settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X,settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y)) + bindButtonReleaseFunction([main_window.minimize_sidebar_button_container, main_window.minimize_sidebar_button], disableCompactMode) + + else: + image_file = CTkImage(getImageFileFromUiUtils(settings.image_filename.ARROW_LEFT),size=(settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X,settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y)) + bindButtonReleaseFunction([main_window.minimize_sidebar_button_container, main_window.minimize_sidebar_button], enableCompactMode) + + main_window.minimize_sidebar_button_container.grid_rowconfigure((0,2), weight=1) + main_window.minimize_sidebar_button.configure(image=image_file) + main_window.minimize_sidebar_button_container.grid(row=0, column=0, sticky="nsw") + main_window.minimize_sidebar_button.grid(row=1, column=0, padx=0, pady=0) + + + bindEnterAndLeaveColor([main_window.minimize_sidebar_button, main_window.minimize_sidebar_button_container], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR) + bindButtonPressColor([main_window.minimize_sidebar_button, main_window.minimize_sidebar_button_container], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR) + + + + diff --git a/vrct_gui/main_window/widgets/create_sidebar.py b/vrct_gui/main_window/widgets/create_sidebar.py new file mode 100644 index 00000000..1b290954 --- /dev/null +++ b/vrct_gui/main_window/widgets/create_sidebar.py @@ -0,0 +1,622 @@ +from customtkinter import CTkOptionMenu, CTkFont, CTkFrame, CTkLabel, CTkSwitch, CTkImage, StringVar + +from ...ui_utils import getImageFileFromUiUtils, openImageKeepAspectRatio, retag, getLatestHeight, bindEnterAndLeaveColor, bindButtonPressColor, bindEnterAndLeaveFunction, bindButtonReleaseFunction, bindButtonPressAndReleaseFunction, setDefaultActiveTab, bindButtonFunctionAndColor, switchActiveTabAndPassiveTab, switchTabsColor + +from time import sleep + + +def createSidebar(settings, main_window): + from vrct_gui import vrct_gui + changeMainWindowWidgetsStatus = vrct_gui.changeMainWindowWidgetsStatus + + + + + + def toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, mark): + mark.place(relx=0.85) if is_turned_on else mark.place(relx=-1) + + + def toggleTranslationFeature(): + is_turned_on = getattr(main_window, "translation_switch_box").get() + print(is_turned_on) + toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, main_window.translation_selected_mark) + toggleTranslationFeatures = [toggleTranslationFeature] + + def toggleTranscriptionSendFeature(): + is_turned_on = getattr(main_window, "transcription_send_switch_box").get() + print(is_turned_on) + toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, main_window.transcription_send_selected_mark) + if is_turned_on is True: + changeMainWindowWidgetsStatus("disabled", "All") + sleep(1.5) + changeMainWindowWidgetsStatus("normal", "All") + + def toggleTranscriptionReceiveFeature(): + is_turned_on = getattr(main_window, "transcription_receive_switch_box").get() + print(is_turned_on) + toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, main_window.transcription_receive_selected_mark) + if is_turned_on is True: + changeMainWindowWidgetsStatus("disabled", "All") + sleep(1.5) + changeMainWindowWidgetsStatus("normal", "All") + + + def toggleForegroundFeature(): + is_turned_on = getattr(main_window, "foreground_switch_box").get() + print(is_turned_on) + toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, main_window.foreground_selected_mark) + + + + + def toggleTranslationSwitchBox(e): + main_window.translation_switch_box.toggle() + + def toggleTranscriptionSendSwitchBox(e): + main_window.transcription_send_switch_box.toggle() + + def toggleTranscriptionReceiveSwitchBox(e): + main_window.transcription_receive_switch_box.toggle() + + def toggleForegroundSwitchBox(e): + main_window.foreground_switch_box.toggle() + + + def changeSidebarFeaturesColorByEvents(ww, event_name): + target_frame_widget = getattr(main_window, ww) + if event_name == "enter": + target_frame_widget.configure(fg_color=settings.ctm.SF__HOVERED_BG_COLOR) + target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_HOVERED_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR) + target_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR) + + elif event_name == "leave": + target_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR) + target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR) + target_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR) + + elif event_name == "button_press": + target_frame_widget.configure(fg_color=settings.ctm.SF__CLICKED_BG_COLOR) + target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_CLICKED_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR) + target_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR) + + elif event_name == "button_release": + target_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR) + target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR) + target_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR) + + + + + + def switchActiveAndPassivePresetsTabsColor(target_active_widget): + quick_setting_tabs = [ + getattr(main_window, "sqls__presets_button_1"), + getattr(main_window, "sqls__presets_button_2"), + getattr(main_window, "sqls__presets_button_3") + ] + + switchTabsColor( + target_widget=target_active_widget, + tab_buttons=quick_setting_tabs, + active_bg_color=settings.ctm.SQLS__PRESETS_TAB_BG_ACTIVE_COLOR, + active_text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR, + passive_bg_color=settings.ctm.SIDEBAR_BG_COLOR, + passive_text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE + ) + + def switchPresetTabFunction(target_active_widget): + switchActiveAndPassivePresetsTabsColor(target_active_widget) + switchActiveTabAndPassiveTab(target_active_widget, main_window.current_active_preset_tab, main_window.current_active_preset_tab.passive_function, settings.ctm.SQLS__PRESETS_TAB_BG_HOVERED_COLOR, settings.ctm.SQLS__PRESETS_TAB_BG_CLICKED_COLOR, settings.ctm.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR) + + main_window.sqls__optionmenu_your_language.configure(variable=StringVar(value=main_window.YOUR_LANGUAGE)) + main_window.sqls__optionmenu_target_language.configure(variable=StringVar(value=main_window.TARGET_LANGUAGE)) + main_window.current_active_preset_tab = target_active_widget + + + + + + + + def switchToPreset1(e): + print("1") + main_window.YOUR_LANGUAGE = "Japanese\n(Japan)" + main_window.TARGET_LANGUAGE = "English\n(United States)" + target_active_widget = getattr(main_window, "sqls__presets_button_1") + switchPresetTabFunction(target_active_widget) + + def switchToPreset2(e): + print("2") + main_window.YOUR_LANGUAGE = "English\n(United States)" + main_window.TARGET_LANGUAGE = "Japanese\n(Japan)" + target_active_widget = getattr(main_window, "sqls__presets_button_2") + switchPresetTabFunction(target_active_widget) + + def switchToPreset3(e): + print("3") + main_window.YOUR_LANGUAGE = "Japanese\n(Japan)" + main_window.TARGET_LANGUAGE = "Chinese, Cantonese\n(Traditional Hong Kong)" + target_active_widget = getattr(main_window, "sqls__presets_button_3") + switchPresetTabFunction(target_active_widget) + + + + + + def createOption_DropdownMenu_for_quickSettings(setattr_obj, parent_widget, optionmenu_attr_name, dropdown_menu_attr_name, dropdown_menu_values=None, width:int = 200, font_size:int = 10, text_color="white", command=None, variable=""): + setattr(setattr_obj, optionmenu_attr_name, CTkOptionMenu( + parent_widget, + height=30, + width=width, + values=dropdown_menu_values, + button_color=settings.ctm.SQLS__DROPDOWN_MENU_BG_COLOR, + fg_color=settings.ctm.SQLS__DROPDOWN_MENU_BG_COLOR, + text_color=text_color, + font=CTkFont(family=settings.FONT_FAMILY, size=font_size, weight="normal"), + variable=variable, + anchor="center", + )) + target_optionmenu_attr = getattr(setattr_obj, optionmenu_attr_name) + target_optionmenu_attr.grid(row=0, column=0, sticky="e") + + + + + def createQuickLanguageSettingBox(parent_widget, title_text, title_text_attr_name, optionmenu_attr_name, dropdown_menu_attr_name, dropdown_menu_values, variable): + sqls__box = CTkFrame(parent_widget, corner_radius=0, fg_color=settings.ctm.SQLS__BOX_BG_COLOR, width=0, height=0) + + sqls__box.columnconfigure((0,2), weight=1) + + sqls__box_wrapper = CTkFrame(sqls__box, corner_radius=0, fg_color=settings.ctm.SQLS__BOX_BG_COLOR, width=0, height=0) + sqls__box_wrapper.grid(row=2, column=1, padx=0, pady=settings.uism.SQLS__BOX_IPADY) + + sqls__label = CTkLabel( + sqls__box_wrapper, + text=title_text, + height=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SQLS__BOX_SECTION_TITLE_FONT_SIZE, weight="normal"), + text_color=settings.ctm.SQLS__BOX_SECTION_TITLE_TEXT_COLOR + ) + sqls__label.grid(row=0, column=0, pady=(0,settings.uism.SQLS__BOX_SECTION_TITLE_BOTTOM_PADY)) + setattr(main_window, title_text_attr_name, sqls__label) + + + + + createOption_DropdownMenu_for_quickSettings( + main_window, + sqls__box_wrapper, + optionmenu_attr_name, + dropdown_menu_attr_name, + dropdown_menu_values=dropdown_menu_values, + # command=self.fakeCommand, + width=settings.uism.SQLS__BOX_DROPDOWN_MENU_WIDTH, + font_size=settings.uism.SQLS__BOX_DROPDOWN_MENU_FONT_SIZE, + text_color=settings.ctm.LABELS_TEXT_COLOR, + variable=variable, + # variable=StringVar(value="Chinese, Cantonese\n(Traditional Hong Kong)"), + ) + getattr(main_window, optionmenu_attr_name).grid(row=1, column=0, padx=0, pady=0) + + return sqls__box + + + + + + + # Side Bar Container + main_window.sidebar_bg_container = CTkFrame(main_window, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0) + main_window.sidebar_bg_container.grid(row=0, column=0, sticky="nsew") + + + MIN_SIDEBAR_WIDTH = settings.uism.COMPACT_MODE_SIDEBAR_WIDTH if settings.IS_SIDEBAR_COMPACT_MODE is True else settings.uism.SIDEBAR_WIDTH + main_window.sidebar_bg_container.grid_columnconfigure(0, weight=0, minsize=MIN_SIDEBAR_WIDTH) + main_window.grid_rowconfigure(0, weight=1) + + + (img, width, height) = openImageKeepAspectRatio(settings.image_filename.VRCT_LOGO, settings.uism.SF__LOGO_MAX_SIZE) + main_window.sidebar_logo = CTkLabel( + main_window.sidebar_bg_container, + fg_color=settings.ctm.SIDEBAR_BG_COLOR, + text=None, + height=0, + image=CTkImage(img, size=(width,height)) + ) + + # "height-a_s" represents the adjustment in size, and the "pady+a_s/2" indicates a padding increase of 4 pixels to compensate for the reduction. + a_s = settings.uism.SF__LOGO_HEIGHT_FOR_ADJUSTMENT + (img, width, height) = openImageKeepAspectRatio(settings.image_filename.VRCT_LOGO_MARK, height-a_s) + main_window.sidebar_compact_mode_logo = CTkLabel( + main_window.sidebar_bg_container, + fg_color=settings.ctm.SIDEBAR_BG_COLOR, + text=None, + height=0, + image=CTkImage(img, size=(width,height)) + ) + + if settings.IS_SIDEBAR_COMPACT_MODE is True: + main_window.sidebar_compact_mode_logo.grid(row=0, column=0, pady=( + int(settings.uism.SF__LOGO_PADY[0]+a_s/2), + int(settings.uism.SF__LOGO_PADY[1]+a_s/2) + )) + else: + main_window.sidebar_logo.grid(row=0, column=0, pady=settings.uism.SF__LOGO_PADY) + + # Sidebar Features + main_window.sidebar_features_container = CTkFrame(main_window.sidebar_bg_container, corner_radius=0, fg_color="transparent", width=0, height=0) + main_window.sidebar_features_container.grid(row=1, column=0, pady=0, sticky="ew") + main_window.sidebar_features_container.grid_columnconfigure(0, weight=1) + + + + sidebar_features_settings = [ + { + "frame_attr_name": "translation_frame", + "command": lambda:[func() for func in toggleTranslationFeatures], + "switch_box_attr_name": "translation_switch_box", + "toggle_switch_box_command": toggleTranslationSwitchBox, + "label_attr_name": "label_translation", + "compact_mode_icon_attr_name": "translation_compact_mode_icon", + "selected_mark_attr_name": "translation_selected_mark", + "text": "Translation", + "icon_file_name": settings.image_filename.TRANSLATION_ICON, + }, + { + "frame_attr_name": "transcription_send_frame", + "command": toggleTranscriptionSendFeature, + "switch_box_attr_name": "transcription_send_switch_box", + "toggle_switch_box_command": toggleTranscriptionSendSwitchBox, + "label_attr_name": "label_transcription_send", + "compact_mode_icon_attr_name": "transcription_send_compact_mode_icon", + "selected_mark_attr_name": "transcription_send_selected_mark", + "text": "Voice2chatbox", + "icon_file_name": settings.image_filename.MIC_ICON, + }, + { + "frame_attr_name": "transcription_receive_frame", + "command": toggleTranscriptionReceiveFeature, + "switch_box_attr_name": "transcription_receive_switch_box", + "toggle_switch_box_command": toggleTranscriptionReceiveSwitchBox, + "label_attr_name": "label_transcription_receive", + "compact_mode_icon_attr_name": "transcription_receive_compact_mode_icon", + "selected_mark_attr_name": "transcription_receive_selected_mark", + "text": "Speaker2chatbox", + "icon_file_name": settings.image_filename.HEADPHONES_ICON, + }, + { + "frame_attr_name": "foreground_frame", + "command": toggleForegroundFeature, + "switch_box_attr_name": "foreground_switch_box", + "toggle_switch_box_command": toggleForegroundSwitchBox, + "label_attr_name": "label_foreground", + "compact_mode_icon_attr_name": "foreground_compact_mode_icon", + "selected_mark_attr_name": "foreground_selected_mark", + "text": "Foreground", + "icon_file_name": settings.image_filename.FOREGROUND_ICON, + }, + ] + + + + row=0 + for sfs in sidebar_features_settings: + frame_attr_name = sfs["frame_attr_name"] + command = sfs["command"] + switch_box_attr_name = sfs["switch_box_attr_name"] + toggle_switch_box_command = sfs["toggle_switch_box_command"] + label_attr_name = sfs["label_attr_name"] + compact_mode_icon_attr_name = sfs["compact_mode_icon_attr_name"] + selected_mark_attr_name = sfs["selected_mark_attr_name"] + text = sfs["text"] + icon_file_name = sfs["icon_file_name"] + + frame_widget = CTkFrame(main_window.sidebar_features_container, corner_radius=0, fg_color=settings.ctm.SF__BG_COLOR, cursor="hand2", width=0, height=0) + setattr(main_window, frame_attr_name, frame_widget) + + frame_widget.grid(row=row, column=0, pady=(0,1), sticky="ew") + frame_widget.grid_columnconfigure(0, weight=1) + + label_widget = CTkLabel( + frame_widget, + text=text, + height=0, + corner_radius=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SF__LABEL_FONT_SIZE, weight="normal"), + anchor="w", + text_color=settings.ctm.LABELS_TEXT_COLOR, + ) + setattr(main_window, label_attr_name, label_widget) + + + switch_box_widget = CTkSwitch( + frame_widget, + text=None, + height=0, + width=0, + corner_radius=int(settings.uism.SF__SWITCH_BOX_HEIGHT/2), + border_width=0, + switch_height=settings.uism.SF__SWITCH_BOX_HEIGHT, + switch_width=settings.uism.SF__SWITCH_BOX_WIDTH, + onvalue=True, + offvalue=False, + command=command, + fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR, + bg_color=settings.ctm.SF__BG_COLOR, + progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR, + ) + # # if sfs["is_checked"] is True: + # # target_attr.select() + # # else: + # # target_attr.deselect() + setattr(main_window, switch_box_attr_name, switch_box_widget) + + + if settings.COMPACT_MODE_ICON_SIZE == 0: + label_widget.grid(row=row, column=0, pady=settings.uism.SF__LABELS_IPADY, padx=(settings.uism.SF__LABEL_LEFT_PAD,0), sticky="ew") + settings.COMPACT_MODE_ICON_SIZE = int(getLatestHeight(frame_widget) - settings.uism.SF__COMPACT_MODE_ICON_PADY*2) + label_widget.grid_remove() + + + # for compact mode + compact_mode_icon_widget = CTkLabel( + frame_widget, + text=None, + height=0, + corner_radius=0, + image=CTkImage(getImageFileFromUiUtils(icon_file_name),size=(settings.COMPACT_MODE_ICON_SIZE,settings.COMPACT_MODE_ICON_SIZE)), + ) + setattr(main_window, compact_mode_icon_attr_name, compact_mode_icon_widget) + + selected_mark_widget = CTkFrame(frame_widget, corner_radius=0, fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR, width=settings.uism.SF__SELECTED_MARK_WIDTH, height=0) + setattr(main_window, selected_mark_attr_name, selected_mark_widget) + + + # Arrange + if settings.IS_SIDEBAR_COMPACT_MODE is True: + compact_mode_icon_widget.grid(row=row, column=0, pady=settings.uism.SF__COMPACT_MODE_ICON_PADY) + selected_mark_widget.place(relx=-1, rely=0.5, relheight=0.75, anchor="center") + else: + label_widget.grid(row=row, column=0, pady=settings.uism.SF__LABELS_IPADY, padx=(settings.uism.SF__LABEL_LEFT_PAD,0), sticky="ew") + switch_box_widget.grid(row=row, column=0, padx=(0,settings.uism.SF__SWITCH_BOX_RIGHT_PAD), sticky="e") + + + # Unbind the event "" originally set up by the widget to manually control it. + switch_box_widget._canvas.unbind("") + switch_box_widget._text_label.unbind("") + + bindButtonReleaseFunction([compact_mode_icon_widget, frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], toggle_switch_box_command) + + retag("vrct_"+frame_attr_name, compact_mode_icon_widget, frame_widget, label_widget, selected_mark_widget, switch_box_widget) + + def commonEventFunction(e, event_type): + for ww in e.widget.master.bindtags(): + if ww.startswith("vrct_"): + ww = ww.replace("vrct_", "") + changeSidebarFeaturesColorByEvents(ww, event_type) + break + + def enterFunction(e): + commonEventFunction(e, "enter") + + def leaveFunction(e): + commonEventFunction(e, "leave") + + def buttonPressFunction(e): + commonEventFunction(e, "button_press") + + def buttonReleasedFunction(e): + commonEventFunction(e, "button_release") + + bindEnterAndLeaveFunction([compact_mode_icon_widget, frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], enterFunction, leaveFunction) + + bindButtonPressAndReleaseFunction([compact_mode_icon_widget, frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], buttonPressFunction, buttonReleasedFunction) + + row+=1 + + + + + + # Sidebar Quick Language Settings, SQLS + main_window.sqls__container = CTkFrame(main_window.sidebar_bg_container, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0) + + if settings.IS_SIDEBAR_COMPACT_MODE is False: + main_window.sqls__container.grid(row=2, column=0, sticky="new") + + main_window.sqls__container.grid_columnconfigure(0, weight=1) + + + main_window.sqls__container_title = CTkLabel(main_window.sqls__container, + # text="言語設定", + text="Language Settings", + height=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SQLS__TITLE_FONT_SIZE, weight="normal"), + text_color=settings.ctm.SQLS__TITLE_TEXT_COLOR + ) + main_window.sqls__container_title.grid(row=0, column=0, pady=settings.uism.SQLS__TITLE_PADY, sticky="nsew") + + + + # Presets buttons + main_window.sidebar_bg_container.grid_rowconfigure(2, weight=1) + main_window.sqls__presets_buttons_box = CTkFrame(main_window.sqls__container, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0) + main_window.sqls__presets_buttons_box.grid(row=1, column=0, sticky="ew") + + main_window.sqls__presets_buttons_box.grid_columnconfigure((0,1,2), weight=1) + + + preset_tabs_settings = [ + { + "preset_tab_attr_name": "sqls__presets_button_1", + "command": switchToPreset1, + "text": "1", + }, + { + "preset_tab_attr_name": "sqls__presets_button_2", + "command": switchToPreset2, + "text": "2", + }, + { + "preset_tab_attr_name": "sqls__presets_button_3", + "command": switchToPreset3, + "text": "3", + }, + ] + + column=0 + for preset_tab_settings in preset_tabs_settings: + preset_tab_attr_name = preset_tab_settings["preset_tab_attr_name"] + command = preset_tab_settings["command"] + text = preset_tab_settings["text"] + + setattr( + main_window, + preset_tab_attr_name, + CTkFrame( + main_window.sqls__presets_buttons_box, + corner_radius=0, + fg_color=settings.ctm.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR, + width=0, + height=30, + cursor="hand2", + ) + ) + parent_widget = getattr(main_window, preset_tab_attr_name) + parent_widget.grid(row=0, column=column, sticky="ew") + + label_widget = CTkLabel( + parent_widget, + text=text, + height=0, + fg_color=settings.ctm.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SQLS__PRESET_TAB_NUMBER_FONT_SIZE, weight="bold"), + anchor="center", + text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE + ) + label_widget.place(relx=0.5, rely=0.5, anchor="center") + + + + bindEnterAndLeaveColor([parent_widget, label_widget], settings.ctm.SQLS__PRESETS_TAB_BG_HOVERED_COLOR, settings.ctm.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR) + bindButtonPressColor([parent_widget, label_widget], settings.ctm.SQLS__PRESETS_TAB_BG_CLICKED_COLOR, settings.ctm.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR) + + parent_widget.passive_function = command + bindButtonReleaseFunction([parent_widget, label_widget], command) + + column+=1 + + # Set default active preset tab + main_window.current_active_preset_tab = getattr(main_window, "sqls__presets_button_1") + setDefaultActiveTab( + active_tab_widget=main_window.current_active_preset_tab, + active_bg_color=settings.ctm.SQLS__PRESETS_TAB_BG_ACTIVE_COLOR, + active_text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR + ) + + + # Quick Language settings BOX + main_window.sqls__box_frame = CTkFrame(main_window.sqls__container, corner_radius=0, fg_color=settings.ctm.SQLS__BG_COLOR, width=0, height=0) + main_window.sqls__box_frame.grid(row=2, column=0, sticky="ew") + main_window.sqls__box_frame.grid_columnconfigure(0, weight=1) + + # Your language + main_window.sqls__box_your_language = createQuickLanguageSettingBox( + parent_widget=main_window.sqls__box_frame, + # title_text="あなたの言語", + title_text="Your Language", + title_text_attr_name="sqls__title_text_your_language", + optionmenu_attr_name="sqls__optionmenu_your_language", + dropdown_menu_attr_name="sqls__dropdown_menu_your_language", + dropdown_menu_values=["1""2","pppp\npppp"], + variable=StringVar(value=main_window.YOUR_LANGUAGE) + ) + main_window.sqls__box_your_language.grid(row=2, column=0, padx=0, pady=(settings.uism.SQLS__BOX_TOP_PADY,0),sticky="ew") + + + # Both direction arrow icon + main_window.sqls__arrow_direction_box = CTkFrame(main_window.sqls__box_frame, corner_radius=0, fg_color=settings.ctm.SQLS__BG_COLOR, width=0, height=0) + main_window.sqls__arrow_direction_box.grid(row=3, column=0, padx=0, pady=settings.uism.SQLS__BOX_ARROWS_PADY,sticky="ew") + + main_window.sqls__arrow_direction_box.grid_columnconfigure((0,4), weight=1) + + main_window.sqls__both_direction_up = CTkLabel( + main_window.sqls__arrow_direction_box, + text=None, + height=0, + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.NARROW_ARROW_DOWN).rotate(180),size=settings.uism.SQLS__BOX_ARROWS_IMAGE_SIZE) + + ) + main_window.sqls__both_direction_up.grid(row=0, column=1, pady=0) + + main_window.sqls__both_direction_desc = CTkLabel( + main_window.sqls__arrow_direction_box, + # text="双方向に翻訳", + text="Translate Each Other", + height=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SQLS__BOX_ARROWS_DESC_FONT_SIZE, weight="normal"), + text_color=settings.ctm.SQLS__BOX_ARROWS_TEXT_COLOR, + ) + main_window.sqls__both_direction_desc.grid(row=0, column=2, padx=settings.uism.SQLS__BOX_ARROWS_DESC_PADX, pady=0) + + main_window.sqls__both_direction_label_down = CTkLabel( + main_window.sqls__arrow_direction_box, + text=None, + height=0, + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.NARROW_ARROW_DOWN).rotate(0),size=settings.uism.SQLS__BOX_ARROWS_IMAGE_SIZE) + + ) + main_window.sqls__both_direction_label_down.grid(row=0, column=3, pady=0) + + + + # Target language + main_window.sqls__box_target_language = createQuickLanguageSettingBox( + parent_widget=main_window.sqls__box_frame, + # title_text="相手の言語", + title_text="Target Language", + title_text_attr_name="sqls__title_text_target_language", + optionmenu_attr_name="sqls__optionmenu_target_language", + dropdown_menu_attr_name="sqls__dropdown_menu_target_language", + dropdown_menu_values=["1""2","pppp\npppp2"], + variable=StringVar(value=main_window.TARGET_LANGUAGE) + ) + main_window.sqls__box_target_language.grid(row=4, column=0, padx=0, pady=(0,0),sticky="ew") + + + + + + # Config Button + main_window.sidebar_config_button_container = CTkFrame(main_window.sidebar_bg_container, corner_radius=0, fg_color=settings.ctm.CONFIG_BUTTON_BG_COLOR, width=0, height=0) + main_window.sidebar_config_button_container.grid(row=3, column=0, sticky="ew") + + + main_window.sidebar_config_button_container.grid_columnconfigure(0, weight=1) + main_window.sidebar_config_button_wrapper = CTkFrame(main_window.sidebar_config_button_container, corner_radius=settings.uism.SIDEBAR_CONFIG_BUTTON_CORNER_RADIUS, fg_color=settings.ctm.CONFIG_BUTTON_BG_COLOR, height=0, width=0, cursor="hand2") + main_window.sidebar_config_button_wrapper.grid(row=0, column=0, padx=settings.uism.SIDEBAR_CONFIG_BUTTON_PADX, pady=settings.uism.SIDEBAR_CONFIG_BUTTON_PADY, sticky="ew") + + + + + main_window.sidebar_config_button_wrapper.grid_columnconfigure(0, weight=1) + + settings.uism.CONFIG_BUTTON_PADX= 0 + main_window.sidebar_config_button = CTkLabel( + main_window.sidebar_config_button_wrapper, + text=None, + height=0, + image=CTkImage(getImageFileFromUiUtils(settings.image_filename.CONFIGURATION_ICON),size=(settings.COMPACT_MODE_ICON_SIZE,settings.COMPACT_MODE_ICON_SIZE)) + ) + main_window.sidebar_config_button.grid(row=0, column=0, padx=0, pady=settings.uism.SIDEBAR_CONFIG_BUTTON_IPADY) + + + bindButtonFunctionAndColor( + target_widgets=[main_window.sidebar_config_button_wrapper, main_window.sidebar_config_button], + enter_color=settings.ctm.CONFIG_BUTTON_HOVERED_BG_COLOR, + leave_color=settings.ctm.CONFIG_BUTTON_BG_COLOR, + clicked_color=settings.ctm.CONFIG_BUTTON_CLICKED_BG_COLOR, + buttonReleasedFunction=main_window.openConfigWindow, + ) + diff --git a/vrct_gui/main_window/widgets/create_textbox.py b/vrct_gui/main_window/widgets/create_textbox.py new file mode 100644 index 00000000..1bc4a05b --- /dev/null +++ b/vrct_gui/main_window/widgets/create_textbox.py @@ -0,0 +1,177 @@ +from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkTextbox + +from ...ui_utils import getLatestWidth, getLongestText, bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, setDefaultActiveTab, switchActiveTabAndPassiveTab, switchTabsColor + + +def createTextbox(settings, main_window): + + def switchTextbox(target_textbox_attr_name): + main_window.current_active_textbox.grid_remove() + main_window.current_active_textbox = getattr(main_window, target_textbox_attr_name) + main_window.current_active_textbox.grid() + + def switchToTextboxAll(e): + print("switchToTextboxAll") + target_active_widget = getattr(main_window, "textbox_tab_all") + switchTextboxTabFunction(target_active_widget) + switchTextbox("textbox_all") + + def switchToTextboxSent(e): + print("switchToTextboxSent") + target_active_widget = getattr(main_window, "textbox_tab_sent") + switchTextboxTabFunction(target_active_widget) + switchTextbox("textbox_sent") + + def switchToTextboxReceived(e): + print("switchToTextboxReceived") + target_active_widget = getattr(main_window, "textbox_tab_received") + switchTextboxTabFunction(target_active_widget) + switchTextbox("textbox_received") + + def switchToTextboxSystem(e): + print("switchToTextboxSystem") + target_active_widget = getattr(main_window, "textbox_tab_system") + switchTextboxTabFunction(target_active_widget) + switchTextbox("textbox_system") + + + def switchTextboxTabFunction(target_active_widget): + switchActiveAndPassiveTextboxTabsColor(target_active_widget) + switchActiveTabAndPassiveTab(target_active_widget, main_window.current_active_textbox_tab, main_window.current_active_textbox_tab.passive_function, settings.ctm.TEXTBOX_TAB_BG_HOVERED_COLOR, settings.ctm.TEXTBOX_TAB_BG_CLICKED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR) + main_window.current_active_textbox_tab = target_active_widget + + def switchActiveAndPassiveTextboxTabsColor(target_active_widget): + textbox_tabs = [ + getattr(main_window, "textbox_tab_all"), + getattr(main_window, "textbox_tab_sent"), + getattr(main_window, "textbox_tab_received"), + getattr(main_window, "textbox_tab_system") + ] + + switchTabsColor( + target_widget=target_active_widget, + tab_buttons=textbox_tabs, + active_bg_color=settings.ctm.TEXTBOX_BG_COLOR, + active_text_color=settings.ctm.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR, + passive_bg_color=settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR, + passive_text_color=settings.ctm.TEXTBOX_TAB_TEXT_PASSIVE_COLOR + ) + + + + + # Text box + main_window.main_bg_container.grid_rowconfigure(1, weight=1) + main_window.main_textbox_container = CTkFrame(main_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + main_window.main_textbox_container.grid(row=1, column=0, sticky="nsew") + + main_window.main_textbox_container.columnconfigure(0,weight=1) + main_window.main_textbox_container.rowconfigure(0,weight=1) + + main_window.textbox_switch_tabs_container = CTkFrame(main_window.main_topbar_center_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0) + main_window.textbox_switch_tabs_container.place(relx=0.07, rely=1.15, anchor="sw") + + main_window.textbox_switch_tabs_container.grid_columnconfigure((0,1,2,3), weight=1, uniform="textbox_tabs") + + textbox_settings = [ + { + "textbox_tab_attr_name": "textbox_tab_all", + "command": switchToTextboxAll, + "textbox_attr_name": "textbox_all", + "text": "All", + }, + { + "textbox_tab_attr_name": "textbox_tab_sent", + "command": switchToTextboxSent, + "textbox_attr_name": "textbox_sent", + "text": "Sent", + }, + + { + "textbox_tab_attr_name": "textbox_tab_received", + "command": switchToTextboxReceived, + "textbox_attr_name": "textbox_received", + "text": "Received", + }, + + { + "textbox_tab_attr_name": "textbox_tab_system", + "command": switchToTextboxSystem, + "textbox_attr_name": "textbox_system", + "text": "System", + }, + ] + + + longest_text = getLongestText(textbox_settings) + + setattr(main_window, "_mlw", CTkLabel( + main_window, + text=longest_text, + corner_radius=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_TAB_FONT_SIZE, weight="normal"), + height=0, + anchor="center", + )) + label_widget = getattr(main_window, "_mlw") + label_widget.grid() + MAX_LABEL_WIDTH = getLatestWidth(label_widget) + label_widget.grid_remove() + + + column=0 + for textbox_setting in textbox_settings: + setattr(main_window, textbox_setting["textbox_tab_attr_name"], CTkFrame(main_window.textbox_switch_tabs_container, corner_radius=settings.uism.TEXTBOX_TAB_CORNER_RADIUS, fg_color=settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR, cursor="hand2", width=0, height=0) + ) + target_widget = getattr(main_window, textbox_setting["textbox_tab_attr_name"]) + target_widget.grid(row=0, column=column, pady=0, padx=(0,2), sticky="ew") + + + + setattr(main_window, "label_widget", CTkLabel( + target_widget, + text=textbox_setting["text"], + corner_radius=0, + font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_TAB_FONT_SIZE, weight="normal"), + height=0, + width=MAX_LABEL_WIDTH, + anchor="center", + text_color=settings.ctm.TEXTBOX_TAB_TEXT_PASSIVE_COLOR, + )) + label_widget = getattr(main_window, "label_widget") + label_widget.grid(row=0, column=column) + + label_widget.grid(row=0, column=column, pady=settings.uism.TEXTBOX_TAB_PADY, padx=settings.uism.TEXTBOX_TAB_PADX) + + bindEnterAndLeaveColor([target_widget, label_widget], settings.ctm.TEXTBOX_TAB_BG_HOVERED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR) + bindButtonPressColor([target_widget, label_widget], settings.ctm.TEXTBOX_TAB_BG_CLICKED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR) + + target_widget.passive_function = textbox_setting["command"] + bindButtonReleaseFunction([target_widget, label_widget], textbox_setting["command"]) + + + + setattr(main_window, textbox_setting["textbox_attr_name"], CTkTextbox( + main_window.main_textbox_container, + corner_radius=settings.uism.TEXTBOX_CORNER_RADIUS, + fg_color=settings.ctm.TEXTBOX_BG_COLOR, + text_color="lime", # Textbox's text_color is set when printing. so this is for prevent from non-setting text_color like the gloves used in food factories are blue. + )) + textbox_widget = getattr(main_window, textbox_setting["textbox_attr_name"]) + textbox_widget.grid(row=0, column=0, padx=settings.uism.TEXTBOX_PADX, pady=0, sticky="nsew") + textbox_widget.grid_remove() + textbox_widget.configure(state="disabled") + # print_textbox(main_window, textbox_widget, "send", textbox_setting["textbox_attr_name"], "SEND") + + column+=1 + + # Set default active textbox tab + main_window.current_active_textbox_tab = getattr(main_window, "textbox_tab_all") + setDefaultActiveTab( + active_tab_widget=main_window.current_active_textbox_tab, + active_bg_color=settings.ctm.TEXTBOX_TAB_BG_ACTIVE_COLOR, + active_text_color=settings.ctm.TEXTBOX_TAB_TEXT_ACTIVE_COLOR + ) + + main_window.current_active_textbox = getattr(main_window, "textbox_all") + main_window.current_active_textbox.grid() diff --git a/vrct_gui/ui_managers/ColorThemeManager.py b/vrct_gui/ui_managers/ColorThemeManager.py new file mode 100644 index 00000000..df0fbe50 --- /dev/null +++ b/vrct_gui/ui_managers/ColorThemeManager.py @@ -0,0 +1,360 @@ +from types import SimpleNamespace + +class ColorThemeManager(): + def __init__(self, theme): + print(theme) + self.main = SimpleNamespace() + self.config_window = SimpleNamespace() + + self.PRIMARY_100_COLOR = "#c4eac1" + self.PRIMARY_200_COLOR = "#9cdd98" + self.PRIMARY_300_COLOR = "#70d16c" + self.PRIMARY_400_COLOR = "#49c649" + self.PRIMARY_500_COLOR = "#0abb1d" + self.PRIMARY_600_COLOR = "#00ac11" + self.PRIMARY_650_COLOR = "#00A309" + self.PRIMARY_700_COLOR = "#009900" + self.PRIMARY_800_COLOR = "#008800" + self.PRIMARY_900_COLOR = "#006900" + + + self.DARK_100_COLOR = "#f5f7fb" + self.DARK_200_COLOR = "#f1f2f6" + self.DARK_300_COLOR = "#e9eaee" + self.DARK_400_COLOR = "#c7c8cc" + self.DARK_500_COLOR = "#a9aaae" + self.DARK_600_COLOR = "#7f8084" + self.DARK_700_COLOR = "#6a6c6f" + self.DARK_750_COLOR = "#5b5c5f" + self.DARK_800_COLOR = "#4b4c4f" + self.DARK_825_COLOR = "#434447" + self.DARK_850_COLOR = "#3a3b3e" + self.DARK_875_COLOR = "#323336" + self.DARK_888_COLOR = "#2e2f32" + self.DARK_900_COLOR = "#292a2d" + self.DARK_925_COLOR = "#242528" + self.DARK_950_COLOR = "#1f2022" + self.DARK_975_COLOR = "#1a1b1d" + self.DARK_1000_COLOR = "#151517" # THE DARKEST COLOR + + + self.LIGHT_100_COLOR = "#f2f2f2" # THE LIGHTEST COLOR + self.LIGHT_200_COLOR = "#e9e9e9" + self.LIGHT_250_COLOR = "#e1e1e1" + self.LIGHT_300_COLOR = "#d9d9d9" + self.LIGHT_325_COLOR = "#d0d0d0" + self.LIGHT_350_COLOR = "#c7c7c7" + self.LIGHT_375_COLOR = "#bebebe" + self.LIGHT_400_COLOR = "#b5b5b5" + self.LIGHT_450_COLOR = "#a5a5a5" + self.LIGHT_500_COLOR = "#959595" + self.LIGHT_600_COLOR = "#6d6d6d" + self.LIGHT_700_COLOR = "#5a5a5a" + self.LIGHT_750_COLOR = "#515151" + self.LIGHT_800_COLOR = "#3b3b3b" + self.LIGHT_850_COLOR = "#323232" + self.LIGHT_875_COLOR = "#2b2b2b" + self.LIGHT_900_COLOR = "#1b1b1b" + # self.LIGHT_925_COLOR = "#121212" + # self.LIGHT_950_COLOR = "#0c0c0c" + # self.LIGHT_975_COLOR = "#070707" + self.LIGHT_1000_COLOR = "#010101" + + + if theme == "Dark": + self._createDarkModeColor() + elif theme == "Light": + self._createLightModeColor() + + + def _createDarkModeColor(self): + # Common + self.main.BASIC_TEXT_COLOR = self.LIGHT_100_COLOR + self.main.LABELS_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + + # Main + self.main.MAIN_BG_COLOR = self.DARK_900_COLOR + + self.main.TEXTBOX_BG_COLOR = self.DARK_950_COLOR + self.main.TEXTBOX_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + self.main.TEXTBOX_TAB_BG_PASSIVE_COLOR = self.DARK_850_COLOR + self.main.TEXTBOX_TAB_BG_ACTIVE_COLOR = self.main.TEXTBOX_BG_COLOR + self.main.TEXTBOX_TAB_BG_HOVERED_COLOR = self.DARK_800_COLOR + self.main.TEXTBOX_TAB_BG_CLICKED_COLOR = self.DARK_850_COLOR + self.main.TEXTBOX_TAB_TEXT_ACTIVE_COLOR = self.main.BASIC_TEXT_COLOR + self.main.TEXTBOX_TAB_TEXT_PASSIVE_COLOR = self.DARK_500_COLOR + + self.main.TEXTBOX_ENTRY_TEXT_COLOR = self.DARK_300_COLOR + self.main.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR = self.DARK_500_COLOR + self.main.TEXTBOX_ENTRY_BG_COLOR = self.DARK_875_COLOR + self.main.TEXTBOX_ENTRY_BORDER_COLOR = self.DARK_750_COLOR + self.main.TEXTBOX_ENTRY_PLACEHOLDER_COLOR = self.DARK_500_COLOR + self.main.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR = self.DARK_700_COLOR + + + + # Sidebar + self.main.SIDEBAR_BG_COLOR = self.DARK_875_COLOR + + # Sidebar Features + self.main.SF__BG_COLOR = self.DARK_850_COLOR + self.main.SF__HOVERED_BG_COLOR = self.DARK_800_COLOR + self.main.SF__CLICKED_BG_COLOR = self.DARK_900_COLOR + self.main.SF__TEXT_DISABLED_COLOR = self.DARK_500_COLOR + + self.main.SF__SWITCH_BOX_BG_COLOR = self.DARK_800_COLOR + self.main.SF__SWITCH_BOX_HOVERED_BG_COLOR = self.DARK_750_COLOR + self.main.SF__SWITCH_BOX_CLICKED_BG_COLOR = self.DARK_850_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_650_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR = self.PRIMARY_500_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR = self.PRIMARY_700_COLOR + self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR = self.PRIMARY_900_COLOR + + self.main.SF__SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR + self.main.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR + self.main.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR + self.main.SF__SELECTED_MARK_DISABLE_BG_COLOR = self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR + + + # Sidebar quick settings + self.main.SQLS__TITLE_TEXT_COLOR = self.DARK_400_COLOR + + self.main.SQLS__BG_COLOR = self.DARK_825_COLOR + + self.main.SQLS__PRESETS_TAB_BG_HOVERED_COLOR = self.DARK_850_COLOR + self.main.SQLS__PRESETS_TAB_BG_CLICKED_COLOR = self.DARK_888_COLOR + self.main.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.SQLS__PRESETS_TAB_BG_ACTIVE_COLOR = self.main.SQLS__BG_COLOR + self.main.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE = self.DARK_600_COLOR + self.main.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + + self.main.SQLS__BOX_BG_COLOR = self.DARK_850_COLOR + self.main.SQLS__BOX_SECTION_TITLE_TEXT_COLOR = self.DARK_400_COLOR + self.main.SQLS__BOX_ARROWS_TEXT_COLOR = self.DARK_500_COLOR + + self.main.SQLS__DROPDOWN_MENU_BG_COLOR = self.DARK_900_COLOR + + + self.main.CONFIG_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.CONFIG_BUTTON_HOVERED_BG_COLOR = self.DARK_800_COLOR + self.main.CONFIG_BUTTON_CLICKED_BG_COLOR = self.DARK_900_COLOR + # self.main.CONFIG_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR + + self.main.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR = self.DARK_800_COLOR + self.main.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR = self.DARK_900_COLOR + # self.main.MINIMIZE_SIDEBAR_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR + + self.main.HELP_AND_INFO_BUTTON_BG_COLOR = self.main.MAIN_BG_COLOR + self.main.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR = self.DARK_850_COLOR + self.main.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR = self.DARK_950_COLOR + # self.main.HELP_AND_INFO_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR + + + # Common + self.config_window.BASIC_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + self.config_window.LABELS_TEXT_COLOR = self.config_window.BASIC_TEXT_COLOR + self.config_window.LABELS_DESC_TEXT_COLOR = self.DARK_500_COLOR + + + # Top bar + self.config_window.TOP_BAR_BG_COLOR = self.DARK_850_COLOR + + + # Main + self.config_window.MAIN_BG_COLOR = self.DARK_950_COLOR + + # This is for fake border color + self.config_window.SB__WRAPPER_BG_COLOR = self.DARK_750_COLOR + + self.config_window.SB__BG_COLOR = self.DARK_888_COLOR + + self.config_window.SB__OPTIONMENU_BG_COLOR = self.DARK_925_COLOR + self.config_window.SB__OPTIONMENU_HOVERED_BG_COLOR = self.DARK_850_COLOR + + self.config_window.SB__SLIDER_BUTTON_COLOR = self.DARK_700_COLOR + self.config_window.SB__SLIDER_BUTTON_HOVERED_COLOR = self.DARK_600_COLOR + + self.config_window.SB__SWITCH_BOX_BG_COLOR = self.main.SF__SWITCH_BOX_BG_COLOR + self.config_window.SB__SWITCH_BOX_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR + + self.config_window.SB__CHECKBOX_BORDER_COLOR = self.DARK_500_COLOR + self.config_window.SB__CHECKBOX_HOVER_COLOR = self.DARK_800_COLOR + self.config_window.SB__CHECKBOX_CHECKED_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__CHECKBOX_CHECKMARK_COLOR = self.config_window.BASIC_TEXT_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR = self.PRIMARY_500_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR = self.DARK_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR = self.DARK_900_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR = self.DARK_850_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR = self.PRIMARY_600_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR = self.PRIMARY_900_COLOR + # self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_DISABLED_COLOR = self.PRIMARY_900_COLOR + + + # Side menu + self.config_window.SIDE_MENU_BG_COLOR = self.config_window.MAIN_BG_COLOR + + self.config_window.SIDE_MENU_LABELS_BG_COLOR = self.config_window.SIDE_MENU_BG_COLOR + self.config_window.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR = self.config_window.SIDE_MENU_BG_COLOR + self.config_window.SIDE_MENU_LABELS_HOVERED_BG_COLOR = self.DARK_850_COLOR + self.config_window.SIDE_MENU_LABELS_CLICKED_BG_COLOR = self.PRIMARY_900_COLOR + self.config_window.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR = self.PRIMARY_300_COLOR + + self.config_window.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR + + + + + + + + + + def _createLightModeColor(self): + # Common + self.main.BASIC_TEXT_COLOR = self.DARK_1000_COLOR + self.main.LABELS_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + + # Main + self.main.MAIN_BG_COLOR = self.LIGHT_300_COLOR + + self.main.TEXTBOX_BG_COLOR = self.LIGHT_200_COLOR + self.main.TEXTBOX_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + self.main.TEXTBOX_TAB_BG_PASSIVE_COLOR = self.LIGHT_350_COLOR + self.main.TEXTBOX_TAB_BG_ACTIVE_COLOR = self.main.TEXTBOX_BG_COLOR + self.main.TEXTBOX_TAB_BG_HOVERED_COLOR = self.LIGHT_300_COLOR + self.main.TEXTBOX_TAB_BG_CLICKED_COLOR = self.LIGHT_350_COLOR + self.main.TEXTBOX_TAB_TEXT_ACTIVE_COLOR = self.main.BASIC_TEXT_COLOR + self.main.TEXTBOX_TAB_TEXT_PASSIVE_COLOR = self.LIGHT_500_COLOR + + self.main.TEXTBOX_ENTRY_TEXT_COLOR = self.LIGHT_800_COLOR + self.main.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR = self.LIGHT_500_COLOR + self.main.TEXTBOX_ENTRY_BG_COLOR = self.LIGHT_325_COLOR + self.main.TEXTBOX_ENTRY_BORDER_COLOR = self.LIGHT_450_COLOR + self.main.TEXTBOX_ENTRY_PLACEHOLDER_COLOR = self.LIGHT_600_COLOR + self.main.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR = self.LIGHT_700_COLOR + + + + # Sidebar + self.main.SIDEBAR_BG_COLOR = self.LIGHT_375_COLOR + + # Sidebar Features + self.main.SF__BG_COLOR = self.LIGHT_350_COLOR + self.main.SF__HOVERED_BG_COLOR = self.LIGHT_300_COLOR + self.main.SF__CLICKED_BG_COLOR = self.LIGHT_200_COLOR + self.main.SF__TEXT_DISABLED_COLOR = self.LIGHT_500_COLOR + + self.main.SF__SWITCH_BOX_BG_COLOR = self.LIGHT_300_COLOR + self.main.SF__SWITCH_BOX_HOVERED_BG_COLOR = self.LIGHT_450_COLOR + self.main.SF__SWITCH_BOX_CLICKED_BG_COLOR = self.LIGHT_350_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_650_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR = self.PRIMARY_500_COLOR + self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR = self.PRIMARY_700_COLOR + self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR = self.PRIMARY_900_COLOR + + self.main.SF__SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR + self.main.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR + self.main.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR + self.main.SF__SELECTED_MARK_DISABLE_BG_COLOR = self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR + + + # Sidebar quick settings + self.main.SQLS__TITLE_TEXT_COLOR = self.LIGHT_800_COLOR + + self.main.SQLS__BG_COLOR = self.LIGHT_300_COLOR + + self.main.SQLS__PRESETS_TAB_BG_HOVERED_COLOR = self.LIGHT_350_COLOR + self.main.SQLS__PRESETS_TAB_BG_CLICKED_COLOR = self.LIGHT_800_COLOR + self.main.SQLS__PRESETS_TAB_BG_PASSIVE_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.SQLS__PRESETS_TAB_BG_ACTIVE_COLOR = self.main.SQLS__BG_COLOR + self.main.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE = self.LIGHT_600_COLOR + self.main.SQLS__PRESETS_TAB_ACTIVE_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + + self.main.SQLS__BOX_BG_COLOR = self.LIGHT_350_COLOR + self.main.SQLS__BOX_SECTION_TITLE_TEXT_COLOR = self.LIGHT_800_COLOR + self.main.SQLS__BOX_ARROWS_TEXT_COLOR = self.LIGHT_700_COLOR + + self.main.SQLS__DROPDOWN_MENU_BG_COLOR = self.LIGHT_500_COLOR + + + self.main.CONFIG_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.CONFIG_BUTTON_HOVERED_BG_COLOR = self.LIGHT_800_COLOR + self.main.CONFIG_BUTTON_CLICKED_BG_COLOR = self.LIGHT_900_COLOR + # self.main.CONFIG_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR + + self.main.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR + self.main.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR = self.LIGHT_800_COLOR + self.main.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR = self.LIGHT_900_COLOR + # self.main.MINIMIZE_SIDEBAR_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR + + self.main.HELP_AND_INFO_BUTTON_BG_COLOR = self.main.MAIN_BG_COLOR + self.main.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR = self.LIGHT_350_COLOR + self.main.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR = self.LIGHT_450_COLOR + # self.main.HELP_AND_INFO_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR + + + # Common + self.config_window.BASIC_TEXT_COLOR = self.main.BASIC_TEXT_COLOR + self.config_window.LABELS_TEXT_COLOR = self.config_window.BASIC_TEXT_COLOR + self.config_window.LABELS_DESC_TEXT_COLOR = self.DARK_500_COLOR + + + # Top bar + self.config_window.TOP_BAR_BG_COLOR = self.DARK_850_COLOR + + + # Main + self.config_window.MAIN_BG_COLOR = self.DARK_950_COLOR + + # This is for fake border color + self.config_window.SB__WRAPPER_BG_COLOR = self.DARK_750_COLOR + + self.config_window.SB__BG_COLOR = self.DARK_888_COLOR + + self.config_window.SB__OPTIONMENU_BG_COLOR = self.DARK_925_COLOR + self.config_window.SB__OPTIONMENU_HOVERED_BG_COLOR = self.DARK_850_COLOR + + self.config_window.SB__SLIDER_BUTTON_COLOR = self.DARK_700_COLOR + self.config_window.SB__SLIDER_BUTTON_HOVERED_COLOR = self.DARK_600_COLOR + + self.config_window.SB__SWITCH_BOX_BG_COLOR = self.main.SF__SWITCH_BOX_BG_COLOR + self.config_window.SB__SWITCH_BOX_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR + + self.config_window.SB__CHECKBOX_BORDER_COLOR = self.DARK_500_COLOR + self.config_window.SB__CHECKBOX_HOVER_COLOR = self.DARK_800_COLOR + self.config_window.SB__CHECKBOX_CHECKED_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__CHECKBOX_CHECKMARK_COLOR = self.config_window.BASIC_TEXT_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR = self.PRIMARY_500_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR = self.DARK_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR = self.DARK_900_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR = self.DARK_850_COLOR + + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR = self.PRIMARY_700_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR = self.PRIMARY_600_COLOR + self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR = self.PRIMARY_900_COLOR + # self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_DISABLED_COLOR = self.PRIMARY_900_COLOR + + + # Side menu + self.config_window.SIDE_MENU_BG_COLOR = self.config_window.MAIN_BG_COLOR + + self.config_window.SIDE_MENU_LABELS_BG_COLOR = self.config_window.SIDE_MENU_BG_COLOR + self.config_window.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR = self.config_window.SIDE_MENU_BG_COLOR + self.config_window.SIDE_MENU_LABELS_HOVERED_BG_COLOR = self.DARK_850_COLOR + self.config_window.SIDE_MENU_LABELS_CLICKED_BG_COLOR = self.PRIMARY_900_COLOR + self.config_window.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR = self.PRIMARY_300_COLOR + + self.config_window.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR diff --git a/vrct_gui/ui_managers/ImageFilenameManager.py b/vrct_gui/ui_managers/ImageFilenameManager.py new file mode 100644 index 00000000..82573f37 --- /dev/null +++ b/vrct_gui/ui_managers/ImageFilenameManager.py @@ -0,0 +1,54 @@ +class ImageFilenameManager(): + def __init__(self, theme:str ="Dark"): + if theme == "Dark": + return self._createDarkModeImages() + elif theme == "Light": + return self._createLightModeImages() + + + def _createDarkModeImages(self): + self.VRCT_LOGO = "vrct_logo_for_dark_mode.png" + self.VRCT_LOGO_MARK = "vrct_logo_mark_white.png" + + self.TRANSLATION_ICON = "translation_icon_white.png" + self.TRANSLATION_ICON_DISABLED = "translation_icon_disabled.png" + self.MIC_ICON = "mic_icon_white.png" + self.MIC_ICON_DISABLED = "mic_icon_disabled.png" + self.HEADPHONES_ICON = "headphones_icon_white.png" + self.HEADPHONES_ICON_DISABLED = "headphones_icon_disabled.png" + self.FOREGROUND_ICON = "foreground_icon_white.png" + self.FOREGROUND_ICON_DISABLED = "foreground_icon_disabled.png" + + self.NARROW_ARROW_DOWN = "narrow_arrow_down.png" + + self.CONFIGURATION_ICON = "configuration_icon_white.png" + self.CONFIGURATION_ICON_DISABLED = "configuration_icon_disabled.png" + + self.ARROW_LEFT = "arrow_left_white.png" + self.ARROW_LEFT_DISABLED = "arrow_left_disabled.png" + + self.HELP_ICON = "help_icon_white.png" + + def _createLightModeImages(self): + self.VRCT_LOGO = "vrct_logo_for_light_mode.png" + self.VRCT_LOGO_MARK = "vrct_logo_mark_black.png" + + + self.TRANSLATION_ICON = "translation_icon_white.png" + self.TRANSLATION_ICON_DISABLED = "translation_icon_disabled.png" + self.MIC_ICON = "mic_icon_white.png" + self.MIC_ICON_DISABLED = "mic_icon_disabled.png" + self.HEADPHONES_ICON = "headphones_icon_white.png" + self.HEADPHONES_ICON_DISABLED = "headphones_icon_disabled.png" + self.FOREGROUND_ICON = "foreground_icon_white.png" + self.FOREGROUND_ICON_DISABLED = "foreground_icon_disabled.png" + + self.NARROW_ARROW_DOWN = "narrow_arrow_down.png" + + self.CONFIGURATION_ICON = "configuration_icon_white.png" + self.CONFIGURATION_ICON_DISABLED = "configuration_icon_disabled.png" + + self.ARROW_LEFT = "arrow_left_white.png" + self.ARROW_LEFT_DISABLED = "arrow_left_disabled.png" + + self.HELP_ICON = "help_icon_white.png" \ No newline at end of file diff --git a/vrct_gui/ui_managers/UiScalingManager.py b/vrct_gui/ui_managers/UiScalingManager.py new file mode 100644 index 00000000..8d013108 --- /dev/null +++ b/vrct_gui/ui_managers/UiScalingManager.py @@ -0,0 +1,184 @@ +from types import SimpleNamespace + +class UiScalingManager(): + def __init__(self, scaling_percentage): + scaling_float = int(scaling_percentage.replace("%", "")) / 100 + print(scaling_float) + self.SCALING_FLOAT = max(scaling_float, 0.4) + self.main = SimpleNamespace() + self.config_window = SimpleNamespace() + + return self._calculatedUiSizes() + + + + + def _calculatedUiSizes(self): + # Common + + # Main + self.main.TEXTBOX_PADX = self._calculateUiSize(16) + self.main.TEXTBOX_CORNER_RADIUS = self._calculateUiSize(6) + + self.main.TEXTBOX_TAB_CORNER_RADIUS = self._calculateUiSize(8) + self.main.TEXTBOX_TAB_FONT_SIZE = self._calculateUiSize(12) + self.main.TEXTBOX_TAB_PADX = self._calculateUiSize(10) + self.main.TEXTBOX_TAB_PADY = (self._calculateUiSize(4), self._calculateUiSize(10)) + + self.main.TEXTBOX_ENTRY_FONT_SIZE = self._calculateUiSize(16) + self.main.TEXTBOX_ENTRY_HEIGHT = self._calculateUiSize(40) + self.main.TEXTBOX_ENTRY_PADX = self.main.TEXTBOX_PADX + self.main.TEXTBOX_ENTRY_PADY = self._calculateUiSize(10) + self.main.TEXTBOX_ENTRY_IPADX = self._calculateUiSize(14) + self.main.TEXTBOX_ENTRY_IPADY = (self._calculateUiSize(2, True), self._calculateUiSize(3, True)) + + + # Sidebar + self.main.SIDEBAR_WIDTH = self._calculateUiSize(230) + self.main.COMPACT_MODE_SIDEBAR_WIDTH = self._calculateUiSize(60) + + # Sidebar Features + self.main.SF__LOGO_MAX_SIZE = self._calculateUiSize(120) + self.main.SF__LOGO_PADY = (self._calculateUiSize(12),self._calculateUiSize(8)) + self.main.SF__LOGO_HEIGHT_FOR_ADJUSTMENT = (self._calculateUiSize(8)) + + self.main.SF__LABELS_IPADY = self._calculateUiSize(16) + self.main.SF__COMPACT_MODE_ICON_PADY = self.main.SF__LABELS_IPADY + self.main.SF__LABEL_LEFT_PAD = self._calculateUiSize(20) + self.main.SF__LABEL_FONT_SIZE = self._calculateUiSize(16) + + self.main.SF__SWITCH_BOX_RIGHT_PAD = self._calculateUiSize(10) + self.main.SF__SWITCH_BOX_WIDTH = self._calculateUiSize(40) + self.main.SF__SWITCH_BOX_HEIGHT = self._calculateUiSize(16) + + self.main.SF__SELECTED_MARK_WIDTH = self._calculateUiSize(3, True) + + + # Sidebar Quick Language Settings, SQLS + self.main.SQLS__TITLE_FONT_SIZE = self._calculateUiSize(16) + self.main.SQLS__TITLE_PADY = (self._calculateUiSize(12), self._calculateUiSize(6)) + + self.main.SQLS__PRESET_TAB_NUMBER_FONT_SIZE = self._calculateUiSize(16) + + self.main.SQLS__BOX_SECTION_TITLE_FONT_SIZE = self._calculateUiSize(16) + self.main.SQLS__BOX_SECTION_TITLE_BOTTOM_PADY = self._calculateUiSize(10) + self.main.SQLS__BOX_IPADY = (self._calculateUiSize(8),self._calculateUiSize(18)) + self.main.SQLS__BOX_DROPDOWN_MENU_FONT_SIZE = self._calculateUiSize(14) + self.main.SQLS__BOX_DROPDOWN_MENU_WIDTH = self._calculateUiSize(200) + self.main.SQLS__BOX_ARROWS_PADY = self._calculateUiSize(10) + self.main.SQLS__BOX_ARROWS_IMAGE_SIZE = self.dupTuple(self._calculateUiSize(16)) + self.main.SQLS__BOX_ARROWS_DESC_FONT_SIZE = self._calculateUiSize(12) + self.main.SQLS__BOX_ARROWS_DESC_PADX = self._calculateUiSize(6) + self.main.SQLS__BOX_TOP_PADY = self._calculateUiSize(16) + + self.main.SIDEBAR_CONFIG_BUTTON_CORNER_RADIUS = self._calculateUiSize(6) + self.main.SIDEBAR_CONFIG_BUTTON_PADX = self._calculateUiSize(10) + self.main.SIDEBAR_CONFIG_BUTTON_PADY = self._calculateUiSize(10) + self.main.SIDEBAR_CONFIG_BUTTON_IPADY = self._calculateUiSize(8) + + + self.main.HELP_AND_INFO_BUTTON_CORNER_RADIUS = self._calculateUiSize(6) + self.main.HELP_AND_INFO_BUTTON_SIZE = self._calculateUiSize(24) + self.main.HELP_AND_INFO_BUTTON_PADX = (0, self._calculateUiSize(6)) + self.main.HELP_AND_INFO_BUTTON_PADY = (self._calculateUiSize(6),0) + self.main.HELP_AND_INFO_BUTTON_IPADXY = self._calculateUiSize(6) + + self.main.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X = int(self.main.TEXTBOX_PADX/2+self.main.TEXTBOX_CORNER_RADIUS*2) + self.main.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y = self._calculateUiSize(26) + + + + + # Top bar common + self.config_window.TOP_BAR__HEIGHT = self._calculateUiSize(40) + self.config_window.TOP_BAR__IPADY = self._calculateUiSize(12) + + # Top bar Side + self.config_window.TOP_BAR_SIDE__WIDTH = self._calculateUiSize(220) + self.config_window.TOP_BAR_SIDE__CONFIG_LOGO_MARK_SIZE = self.dupTuple(self._calculateUiSize(30)) + self.config_window.TOP_BAR_SIDE__CONFIG_TITLE_FONT_SIZE = self._calculateUiSize(22) + self.config_window.TOP_BAR_SIDE__CONFIG_TITLE_LEFT_PADX = int(self.config_window.TOP_BAR_SIDE__CONFIG_TITLE_FONT_SIZE + self._calculateUiSize(16)) + self.config_window.TOP_BAR_SIDE__TITLE_PADX= self._calculateUiSize(30) + + # Side menu + self.config_window.SIDE_MENU_TOP_PADY= self._calculateUiSize(54) + self.config_window.SIDE_MENU_LABELS_IPADX = self._calculateUiSize(20) + self.config_window.SIDE_MENU_LABELS_IPADY= self._calculateUiSize(8) + self.config_window.SIDE_MENU_LABELS_FONT_SIZE= self._calculateUiSize(18) + + + # Top bar Main + self.config_window.TOP_BAR_MAIN__TITLE_FONT_SIZE = self._calculateUiSize(22) + + + # Setting Box + self.config_window.SB__MAIN_WIDTH = self._calculateUiSize(720) + self.config_window.SB__TOP_PADY_IF_WITH_SECTION_TITLE = (self._calculateUiSize(24)) + self.config_window.SB__TOP_PADY_IF_WITHOUT_SECTION_TITLE = (self._calculateUiSize(64)) + self.config_window.SB__BOTTOM_PADY = (self._calculateUiSize(40)) + self.config_window.SB__IPADX = self._calculateUiSize(20) + self.config_window.SB__IPADY = self._calculateUiSize(12) + self.config_window.SB__BOTTOM_MARGIN = (0, self._calculateUiSize(60)) + + self.config_window.SB__SECTION_TITLE_FONT_SIZE = self._calculateUiSize(20) + self.config_window.SB__SECTION_TITLE_BOTTOM_PADY = (0, self._calculateUiSize(10)) + + self.config_window.SB__LABEL_FONT_SIZE = self._calculateUiSize(16) + self.config_window.SB__DESC_FONT_SIZE = self._calculateUiSize(14) + self.config_window.SB__DESC_TOP_PADY = self._calculateUiSize(2) + + + + self.config_window.SB__SELECTOR_FONT_SIZE = self._calculateUiSize(14) + self.config_window.SB__RADIO_BUTTON_FONT_SIZE = self.config_window.SB__SELECTOR_FONT_SIZE + self.config_window.SB__BUTTON_FONT_SIZE = self.config_window.SB__SELECTOR_FONT_SIZE + + + + self.config_window.SB__OPTION_MENU_FONT_SIZE = self.config_window.SB__SELECTOR_FONT_SIZE + self.config_window.SB__OPTIONMENU_HEIGHT = self._calculateUiSize(30) + self.config_window.SB__OPTIONMENU_WIDTH = self._calculateUiSize(200) + self.config_window.SB__DROPDOWN_MENU_WIDTH = self.config_window.SB__OPTIONMENU_WIDTH + self.config_window.SB__DROPDOWN_MENU_MAX_BUTTON_HEIGHT = int(self.config_window.SB__OPTION_MENU_FONT_SIZE + self._calculateUiSize(6)) + self.config_window.SB__DROPDOWN_MENU_FRAME_CORNER_RADIUS = self._calculateUiSize(10) + self.config_window.SB__DROPDOWN_MENU_FRAME_MAX_HEIGHT = self._calculateUiSize(200) + + + self.config_window.SB__SWITCH_WIDTH = self._calculateUiSize(50) + + self.config_window.SB__SWITCH_BOX_WIDTH = self._calculateUiSize(40) + self.config_window.SB__SWITCH_BOX_HEIGHT = self._calculateUiSize(16) + + self.config_window.SB__CHECKBOX_SIZE = self._calculateUiSize(24) + self.config_window.SB__CHECKBOX_BORDER_WIDTH = self._calculateUiSize(2) + self.config_window.SB__CHECKBOX_CORNER_RADIUS = self._calculateUiSize(4) + + self.config_window.SB__ENTRY_FONT_SIZE = self.config_window.SB__SELECTOR_FONT_SIZE + self.config_window.SB__ENTRY_HEIGHT = self._calculateUiSize(30) + + # SB__ENTRY_WIDTH_10 ... SB__ENTRY_WIDTH_200 + for i in range(10, 201, 10): + setattr(self.config_window, f'SB__ENTRY_WIDTH_{i}', self._calculateUiSize(i)) + + + self.config_window.SB__PROGRESSBAR_X_SLIDER__ENTRY_WIDTH = self.config_window.SB__ENTRY_WIDTH_50 + self.config_window.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT = self.config_window.SB__ENTRY_HEIGHT + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_HEIGHT = self._calculateUiSize(40) + self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_LENGTH = self._calculateUiSize(2) + self.config_window.SB__PROGRESSBAR_X_SLIDER__BAR_WIDTH = self._calculateUiSize(200) + self.config_window.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_HEIGHT = self._calculateUiSize(8) + self.config_window.SB__PROGRESSBAR_X_SLIDER__BAR_RIGHT_PADX = self._calculateUiSize(20) + + self.config_window.SB__PROGRESSBAR_X_SLIDER__BUTTON_RIGHT_PADX = self._calculateUiSize(20) + self.config_window.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY = self._calculateUiSize(10) + self.config_window.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE = self._calculateUiSize(20) + + + + def _calculateUiSize(self, default_size, is_allowed_odd: bool = False): + size = int(default_size * self.SCALING_FLOAT) + size += 1 if not is_allowed_odd and size % 2 != 0 else 0 + return size + + def dupTuple(self, value): + return (value, value) \ No newline at end of file diff --git a/vrct_gui/ui_managers/__init__.py b/vrct_gui/ui_managers/__init__.py new file mode 100644 index 00000000..f6a5abc0 --- /dev/null +++ b/vrct_gui/ui_managers/__init__.py @@ -0,0 +1,3 @@ +from .ColorThemeManager import ColorThemeManager +from .ImageFilenameManager import ImageFilenameManager +from .UiScalingManager import UiScalingManager \ No newline at end of file diff --git a/vrct_gui/ui_utils/__init__.py b/vrct_gui/ui_utils/__init__.py new file mode 100644 index 00000000..bc2a1337 --- /dev/null +++ b/vrct_gui/ui_utils/__init__.py @@ -0,0 +1 @@ +from .ui_utils import * \ No newline at end of file diff --git a/vrct_gui/ui_utils/ui_utils.py b/vrct_gui/ui_utils/ui_utils.py new file mode 100644 index 00000000..eb45ea3d --- /dev/null +++ b/vrct_gui/ui_utils/ui_utils.py @@ -0,0 +1,150 @@ +from os import path as os_path +from PIL.Image import open as Image_open, LANCZOS + +from customtkinter import CTkFrame, CTkLabel, CTkImage + +def getImagePath(file_name): + # root\img\file_name + return os_path.join(os_path.dirname(os_path.dirname(os_path.dirname(__file__))), "img", file_name) + +def getImageFileFromUiUtils(file_name): + # root\img\file_name + img = Image_open(os_path.join(os_path.dirname(os_path.dirname(os_path.dirname(__file__))), "img", file_name)) + return img + +def openImageKeepAspectRatio(file_name, desired_width): + img = getImageFileFromUiUtils(file_name) + wpercent = (desired_width/float(img.size[0])) + hsize = int((float(img.size[1])*float(wpercent))) + img = img.resize((desired_width,hsize), LANCZOS) + return (img, desired_width, hsize) + +def retag(tag, *args): + for widget in args: + widget.bindtags((tag,) + widget.bindtags()) + + +def getLatestWidth(target_widget): + target_widget.update_idletasks() + return target_widget.winfo_width() + +def getLatestHeight(target_widget): + target_widget.update_idletasks() + return target_widget.winfo_height() + +def getLongestText(settings): + max_length = max(len(item["text"]) for item in settings) + max_length = 0 + longest_text = "" + + for item in settings: + if len(item["text"]) > max_length: + max_length = len(item["text"]) + longest_text = item["text"] + return longest_text + +def bindEnterAndLeaveColor(target_widgets, enter_color, leave_color): + for target_widget in target_widgets: + target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=enter_color) for w in widgets], "+") + target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=leave_color) for w in widgets], "+") + + +def bindButtonPressColor(target_widgets, clicked_color, released_color): + for target_widget in target_widgets: + target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=clicked_color) for w in widgets], "+") + target_widget.bind("", lambda e, widgets=target_widgets: [w.configure(fg_color=released_color) for w in widgets], "+") + +def bindEnterAndLeaveFunction(target_widgets, enterFunction, leaveFunction): + for target_widget in target_widgets: + target_widget.bind("", enterFunction, "+") + target_widget.bind("", leaveFunction, "+") + +def bindButtonPressFunction(target_widgets, buttonPressedFunction): + for target_widget in target_widgets: + target_widget.bind("", buttonPressedFunction, "+") + +def bindButtonReleaseFunction(target_widgets, buttonReleasedFunction): + for target_widget in target_widgets: + target_widget.bind("", buttonReleasedFunction, "+") + +def bindButtonPressAndReleaseFunction(target_widgets, buttonPressedFunction, buttonReleasedFunction): + for target_widget in target_widgets: + target_widget.bind("", buttonPressedFunction, "+") + target_widget.bind("", buttonReleasedFunction, "+") + + +def bindButtonFunctionAndColor(target_widgets, enter_color, leave_color, clicked_color, buttonReleasedFunction): + bindEnterAndLeaveColor(target_widgets, enter_color, leave_color) + bindButtonPressColor(target_widgets, clicked_color, enter_color) + bindButtonReleaseFunction(target_widgets, buttonReleasedFunction) + +def unbindEventFromActiveTabWidget(active_tab_widget): + for event_name in ["", "", "", ""]: + active_tab_widget.unbind(event_name) + active_tab_widget.children["!ctklabel"].unbind(event_name) + +def setDefaultActiveTab(active_tab_widget, active_bg_color, active_text_color): + active_tab_widget.configure(fg_color=active_bg_color, cursor="") + active_tab_widget.children["!ctklabel"].configure(fg_color=active_bg_color, text_color=active_text_color) + unbindEventFromActiveTabWidget(active_tab_widget) + + +def switchActiveTabAndPassiveTab(active_tab_widget, current_active_tab_widget, current_active_tab_passive_function, hovered_color, clicked_color, passive_color): + + + active_tab_widget.configure(cursor="") + unbindEventFromActiveTabWidget(active_tab_widget) + + + rebindFunctionToTab(current_active_tab_widget, current_active_tab_passive_function, hovered_color, clicked_color, passive_color) + +def rebindFunctionToTab(passive_tab_widget, passive_tab_function, hovered_color, clicked_color, passive_color): + + passive_tab_widget.configure(cursor="hand2") + bindEnterAndLeaveColor([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], hovered_color, passive_color) + bindButtonPressColor([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], clicked_color, passive_color) + + bindButtonReleaseFunction([passive_tab_widget, passive_tab_widget.children["!ctklabel"]], passive_tab_function) + +def switchTabsColor(target_widget, tab_buttons, active_bg_color, active_text_color, passive_bg_color, passive_text_color): + # Change all tabs' color to passive color at first + for tab_button in tab_buttons: + tab_button.configure(fg_color=passive_bg_color) + tab_button.children["!ctklabel"].configure(fg_color=passive_bg_color, text_color=passive_text_color) + + # Then, set active color to the active tab + target_widget.configure(fg_color=active_bg_color) + target_widget.children["!ctklabel"].configure(fg_color=active_bg_color, text_color=active_text_color) + + + + + + +def createButtonWithImage(parent_widget, button_fg_color, button_enter_color, button_clicked_color, button_image_filename, button_image_size, button_ipadxy, button_command, corner_radius: int = 0 ,shape: str = "normal"): + button_wrapper = CTkFrame(parent_widget, corner_radius=corner_radius, fg_color=button_fg_color, height=0, width=0, cursor="hand2") + + button_widget = CTkLabel( + button_wrapper, + text=None, + height=0, + image=CTkImage(getImageFileFromUiUtils(button_image_filename),size=(button_image_size,button_image_size)), + ) + button_widget.grid(row=0, column=0, padx=button_ipadxy, pady=button_ipadxy) + + bindButtonFunctionAndColor( + target_widgets=[button_wrapper, button_widget], + enter_color=button_enter_color, + leave_color=button_fg_color, + clicked_color=button_clicked_color, + buttonReleasedFunction=button_command, + ) + + if shape == "circle": + # To round the corners of the button into a circle + button_wrapper.grid() + button_wrapper.configure(corner_radius=int(getLatestWidth(button_wrapper)/2)) + button_wrapper.grid_remove() + + + return button_wrapper diff --git a/vrct_gui/vrct_gui.py b/vrct_gui/vrct_gui.py new file mode 100644 index 00000000..795f1b94 --- /dev/null +++ b/vrct_gui/vrct_gui.py @@ -0,0 +1,107 @@ +from types import SimpleNamespace + +from customtkinter import CTk, get_appearance_mode + +# from window_help_and_info import ToplevelWindowInformation + +from .ui_managers import ColorThemeManager, ImageFilenameManager, UiScalingManager +from ._changeMainWindowWidgetsStatus import _changeMainWindowWidgetsStatus +from ._printToTextbox import _printToTextbox + +from .main_window import createMainWindowWidgets +from .config_window import ConfigWindow + +from config import config + + +class VRCT_GUI(CTk): + def __init__(self): + super().__init__() + self.settings = SimpleNamespace() + theme = get_appearance_mode() if config.APPEARANCE_THEME == "System" else config.APPEARANCE_THEME + all_ctm = ColorThemeManager(theme) + all_uism = UiScalingManager(config.UI_SCALING) + image_filename = ImageFilenameManager(theme) + + common_args = { + "image_filename": image_filename, + "FONT_FAMILY": config.FONT_FAMILY, + } + + self.settings.main = SimpleNamespace( + ctm=all_ctm.main, + uism=all_uism.main, + IS_SIDEBAR_COMPACT_MODE=False, + COMPACT_MODE_ICON_SIZE=0, + **common_args + ) + + self.settings.config_window = SimpleNamespace( + ctm=all_ctm.config_window, + uism=all_uism.config_window, + IS_CONFIG_WINDOW_COMPACT_MODE=False, + **common_args + ) + + + self.YOUR_LANGUAGE = "Japanese\n(Japan)" + self.TARGET_LANGUAGE = "English\n(United States)" + + + self.config_window = ConfigWindow(vrct_gui=self, settings=self.settings.config_window) + self.config_window.withdraw() + + # self.information_window = ToplevelWindowInformation(self) + + + + def start(self): + createMainWindowWidgets(vrct_gui=self, settings=self.settings.main) + # self.printToTextbox(self.textbox_all, "Translation started. You: Japanese (japan). Target: English (American english)", "", "INFO") + # self.printToTextbox(self.textbox_all, "テキスト送信テスト", "Test send text", "SEND") + # self.printToTextbox(self.textbox_all, "こんにちは、こんにちは。", "Hi hi hello.", "SEND") + # self.printToTextbox(self.textbox_all, "Hi~ how are you doing.", "やあ~、元気かい?", "RECEIVE") + self.mainloop() + + + def quitVRCT(self): + self.quit() + self.destroy() + + + def openConfigWindow(self, e): + self.config_window.deiconify() + self.config_window.focus_set() + self.config_window.focus() + self.config_window.grab_set() + + def closeConfigWindow(self): + self.config_window.withdraw() + self.config_window.grab_release() + + + + def openHelpAndInfoWindow(self, e): + self.information_window.deiconify() + self.information_window.focus_set() + self.information_window.focus() + + def changeMainWindowWidgetsStatus(self, status, target_names): + _changeMainWindowWidgetsStatus( + vrct_gui=self, + settings=self.settings.main, + status=status, + target_names=target_names, + ) + + def printToTextbox(self, target_textbox, original_message, translated_message, tags=None): + _printToTextbox( + settings=self.settings.main, + target_textbox=target_textbox, + original_message=original_message, + translated_message=translated_message, + tags=tags, + ) + + +vrct_gui = VRCT_GUI() \ No newline at end of file diff --git a/window_help_and_info.py b/window_help_and_info.py new file mode 100644 index 00000000..cc0d3b7f --- /dev/null +++ b/window_help_and_info.py @@ -0,0 +1,154 @@ +import os +from customtkinter import CTkToplevel, CTkTextbox, CTkFont + +class ToplevelWindowInformation(CTkToplevel): + def __init__(self, parent, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + self.withdraw() + self.parent = parent + self.grid_columnconfigure(0, weight=1) + self.grid_rowconfigure(0, weight=1) + # self.geometry(f"{500}x{300}") + self.minsize(500, 300) + + self.after(200, lambda: self.iconbitmap(os.path.join(os.path.dirname(__file__), "img", "app.ico"))) + self.title("Information") + # create textbox information + self.textbox_information = CTkTextbox( + self, + font=CTkFont(family=self.parent.FONT_FAMILY) + ) + self.textbox_information.grid(row=0, column=0, padx=(10, 10), pady=(10, 10), sticky="nsew") + textbox_information_message = """VRCT(v1.3.1) + +# 概要 +VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。 +翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができます。 +(翻訳エンジンはDeepL,Google,Bingに対応) + +# 使用方法 + 初期設定時 + 0. VRChatのOSCを有効にする(重要) + + (任意) + 1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する + 2. ギアアイコンのボタンでconfigウィンドウを開く + 3. ParameterタブのDeepL Auth Keyに認証キーを記載 + 4. configウィンドウを閉じる + + 通常使用時 + 1. メッセージボックスにメッセージを記入 + 2. Enterキーを押し、メッセージを送信する + +# その他の設定 + translation チェックボックス: 翻訳の有効無効 + voice2chatbox チェックボックス : マイクの音声を文字起こししてチャットボックスに送信する + speaker2log チェックボックス : スピーカーの音声から文字起こししてログに表示する + foreground チェックボックス: 最前面表示の有効無効 + + テキストボックス + logタブ + すべてのログを表示 + sendタブ + 送信したメッセージを表示 + receiveタブ + 受信したメッセージを表示 + systemタブ + 機能についてのメッセージを表示 + + configウィンドウ + UIタブ + Transparency: ウィンドウの透過度の調整 + Appearance Theme: ウィンドウテーマを選択 + UI Scaling: UIサイズを調整 + Font Family: 表示フォントを選択 + (New!) UI Language: UIの表示言語を選択 + Translationタブ + Select Translator: 翻訳エンジンの変更 + Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択 + Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択 + Transcriptionタブ + (New!) Input Mic Host: マイクのホストAPIを選択 + Input Mic Device: マイクを選択 + Input Mic Voice Language: 入力する音声の言語 + Input Mic Energy Threshold: 音声取得のしきい値 + (New!) Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化 + Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整 + Input Mic Record Timeout: 音声の区切りの無音時間 + Input Mic Phase Timeout: 文字起こしする音声時間の上限 + Input Mic Max Phrases: 保留する単語の上限 + (New!) Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC) + Input Speaker Device: スピーカーを選択 + Input Speaker Voice Language: 受信する音声の言語 + Input Speaker Energy Threshold: 音声取得のしきい値 + (New!) Check threshold point: (New!)Input Speaker Energy Thresholdのしきい値を視覚化 + Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整 + Input Speaker Record Timeout: 音声の区切りの無音時間 + Input Speaker Phase Timeout: 文字起こしする音声時間の上限 + Input Speaker Max Phrases: 保留する単語の上限 + Parameterタブ + OSC IP address: 変更不要 + OSC port: 変更不要 + DeepL Auth key: DeepLの認証キーの設定 + Message Format: 送信するメッセージのデコレーションの設定 + [message]がメッセージボックスに記入したメッセージに置換される + [translation]が翻訳されたメッセージに置換される + 初期フォーマット:"[message]([translation])" + Othersタブ + (New!) Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする + + 設定の初期化 + config.jsonを削除 + +# お問い合わせ +要望などはTwitterまで +https://twitter.com/misya_ai + +# アップデート履歴 +[2023-05-29: v0.1b] v0.1b リリース +[2023-05-30: v0.2b] +- configボタンをギアアイコンに変更 +- 詳細情報のボタンを追加 +- 翻訳機能有効無効のチェックボックスを追加 +- 最前面表示の有効無効のチェックボックスを追加 +- いくつかのバグを修正 +[2023-06-03: v0.3b] +- 全体的にUIを刷新 +- 透過機能を追加 +- テーマのLight/Dark/Systemのモードの変更機能を追加 +- UIのスケール変更機能を追加 +- フォントの変更機能を追加 +[2023-06-06: v0.4b] +- 翻訳エンジンを追加 +- 入力と出力の翻訳言語を選択できるように変更 +[2023-06-20: v1.0] +- マイクからの音声の文字起こし機能を追加 +- スピーカーからの音声の文字起こし機能を追加 +[2023-06-28: v1.1] +- いくつかのバクを修正 +- 翻訳/文字起こし言語の表記を略称からわかりやすい文字に変更 +- 文字起こしの処理の軽量化 +[2023-07-05: v1.2] +- 文字起こし精度の向上 +[2023-07-21: v1.3] +- UIの表示言語を日本語/英語を選択できる機能を追加 +- Energy Thresholdの視覚化機能を追加 +- 文字起こしの誤認識対策のため、Word Filterを追加 +- WASAPI以外のHostAPIでもマイクとして使用できるようにHostAPIを選択できる機能を追加 +- メッセージ送信後に書き込んだメッセージを空にするか選択できる機能を追加 +- バグ対策のため、translation/voice2chatbox/speaker2log/foregroundは起動時はOFFになるように変更 +- バグ対策のため、スピーカーについて既定デバイス以外を選択した時にERRORが出るように変更 +- 半角入力時に一部の文字が書き込めないバグを修正 +[2023-07-22: v1.3.1] +- UIの表示言語選択に韓国語を追加 + +# 注意事項 +再配布とかはやめてね +""" + + self.textbox_information.insert("end", textbox_information_message) + self.textbox_information.configure(state='disabled') + self.protocol("WM_DELETE_WINDOW", self.delete_window) + + def delete_window(self): + self.withdraw() \ No newline at end of file