[Update] add Update Software Confirmation Modal Window.

This commit is contained in:
Sakamoto Shiina
2023-10-18 14:54:18 +09:00
parent 98ac2232a3
commit 5abfe3c20b
11 changed files with 316 additions and 19 deletions

View File

@@ -44,6 +44,13 @@ main_window:
cover_message: The functionality is temporarily disabled until the settings window is closed.
confirmation_message:
update_software: "Download new version and restart automatically.\nIt'll take a while. Do it now?"
deny_update_software: Do it later
accept_update_software: Update and Restart
updating: Now updating...
selectable_language_window:
title_your_language: Select Your Language

View File

@@ -44,6 +44,13 @@ main_window:
cover_message: 設定画面が閉じられるまで、一時的に機能を停止しています。
confirmation_message:
update_software: "新しいバージョンをダウンロードして再起動します。\n少し時間がかかるかもしれません。今すぐ行いますか"
deny_update_software: 後でする
accept_update_software: アップデートして再起動
updating: アップデート中...
selectable_language_window:
title_your_language: あなたの言語

70
view.py
View File

@@ -10,6 +10,7 @@ from languages import selectable_languages
from customtkinter import StringVar, IntVar, BooleanVar, END as CTK_END, get_appearance_mode
from vrct_gui.ui_managers import ColorThemeManager, ImageFileManager, UiScalingManager
from vrct_gui import vrct_gui
from utils import callFunctionIfCallable
from config import config
@@ -73,20 +74,37 @@ class View():
**common_args
)
self.settings.update_confirmation_modal = SimpleNamespace(
ctm=all_ctm.update_confirmation_modal,
uism=all_uism.update_confirmation_modal,
**common_args
)
self.view_variable = SimpleNamespace(
# Common
CALLBACK_RESTART_SOFTWARE=None,
# Open Config Window
CALLBACK_CLICKED_OPEN_CONFIG_WINDOW_BUTTON=self._openConfigWindow,
CALLBACK_CLICKED_CLOSE_CONFIG_WINDOW_BUTTON=self._closeConfigWindow,
CALLBACK_OPEN_CONFIG_WINDOW=None,
CALLBACK_CLOSE_CONFIG_WINDOW=None,
# Open Help and Information Page
CALLBACK_CLICKED_HELP_AND_INFO=self.openWebPage_VrctDocuments,
# Open Update Page
CALLBACK_CLICKED_UPDATE_AVAILABLE=None,
# For Update Software
# Open Update Confirmation Modal
CALLBACK_CLICKED_UPDATE_AVAILABLE=self._showUpdateSoftwareConfirmationModal,
CALLBACK_UPDATE_SOFTWARE=None,
CALLBACK_ACCEPT_UPDATE=self._startUpdateSoftware,
CALLBACK_DENY_UPDATE=self._deniedUpdateSoftware,
CALLBACK_HIDE_UPDATE_CONFIRMATION_MODAL=self._hideUpdateSoftwareConfirmationModal,
VAR_MESSAGE_CONFIRMATION_MODAL=StringVar(value=""),
VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON=StringVar(value=""),
VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON=StringVar(value=""),
# Main Window
@@ -137,7 +155,7 @@ class View():
# Main Window Cover
VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE=StringVar(value=i18n.t("main_window.cover_message")),
VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE=StringVar(value=""),
# Selectable Language Window
VAR_TITLE_LABEL_SELECTABLE_LANGUAGE=StringVar(value=""),
@@ -353,7 +371,7 @@ class View():
if common_registers is not None:
self.view_variable.CALLBACK_CLICKED_UPDATE_AVAILABLE=common_registers.get("callback_update_software", None)
self.view_variable.CALLBACK_UPDATE_SOFTWARE=common_registers.get("callback_update_software", None)
self.view_variable.CALLBACK_RESTART_SOFTWARE=common_registers.get("callback_restart_software", None)
@@ -548,9 +566,49 @@ class View():
def foregroundOff():
vrct_gui.attributes("-topmost", False)
def _showUpdateSoftwareConfirmationModal(self):
@staticmethod
def _openTheCoverOfMainWindow():
self.foregroundOffIfForegroundEnabled()
self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("")
vrct_gui.main_window_cover.show()
self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.update_software"))
self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_update_software"))
self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_update_software"))
vrct_gui.update_confirmation_modal.show()
vrct_gui.update_confirmation_modal.focus_set()
def _hideUpdateSoftwareConfirmationModal(self):
self._deniedUpdateSoftware()
self.foregroundOnIfForegroundEnabled()
def _startUpdateSoftware(self):
self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.updating"))
vrct_gui.update_confirmation_modal.hide_buttons()
vrct_gui.update()
vrct_gui.update_confirmation_modal.update()
callFunctionIfCallable(self.view_variable.CALLBACK_UPDATE_SOFTWARE)
def _deniedUpdateSoftware(self):
vrct_gui.update_confirmation_modal.hide()
vrct_gui.main_window_cover.hide()
def _openConfigWindow(self):
self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set(i18n.t("main_window.cover_message"))
callFunctionIfCallable(self.view_variable.CALLBACK_OPEN_CONFIG_WINDOW)
vrct_gui._openConfigWindow()
def _closeConfigWindow(self):
callFunctionIfCallable(self.view_variable.CALLBACK_CLOSE_CONFIG_WINDOW)
vrct_gui._closeConfigWindow()
def _openTheCoverOfMainWindow(self):
vrct_gui.main_window_cover.show()
vrct_gui.config_window.lift()

View File

@@ -0,0 +1,173 @@
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
from .ui_utils import fadeInAnimation, setGeometryToCenterOfTheWidget, bindButtonFunctionAndColor
from utils import callFunctionIfCallable
class _CreateConfirmationModal(CTkToplevel):
def __init__(self, attach_window, settings, view_variable):
super().__init__()
self.withdraw()
self.title("")
self.overrideredirect(True)
self.wm_attributes("-toolwindow", True)
self.attach_window = attach_window
self.settings = settings
self._view_variable = view_variable
# self.configure(fg_color="#ff7f50")
self.configure(fg_color=self.settings.ctm.FAKE_BORDER_COLOR)
self.protocol("WM_DELETE_WINDOW", lambda _e: callFunctionIfCallable(self._view_variable.CALLBACK_HIDE_UPDATE_CONFIRMATION_MODAL))
def fucusOutFunction(e):
if str(e.widget) != ".!_createconfirmationmodal": return
callFunctionIfCallable(self._view_variable.CALLBACK_HIDE_UPDATE_CONFIRMATION_MODAL)
self.bind("<FocusOut>", fucusOutFunction, "+")
self.grid_rowconfigure(0,weight=1)
self.grid_columnconfigure(0,weight=1)
self.modal_container = CTkFrame(self, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
self.modal_container.grid(row=0, column=0, padx=self.settings.uism.FAKE_BORDER_SIZE, pady=self.settings.uism.FAKE_BORDER_SIZE)
self.modal_contents_wrapper = CTkFrame(self.modal_container, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
self.modal_contents_wrapper.grid(row=0, column=0, padx=self.settings.uism.CONTENTS_WRAPPER, pady=self.settings.uism.CONTENTS_WRAPPER)
self.modal_contents_wrapper.grid_rowconfigure(1, minsize=self.settings.uism.MARGIN_BETWEEN_MESSAGE_AND_BUTTONS)
self.modal_message_label_wrapper = CTkFrame(self.modal_contents_wrapper, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
self.modal_message_label_wrapper.grid(row=0, column=0)
self.modal_message_label_wrapper.grid_rowconfigure((0,2),weight=1)
self.modal_message_label_wrapper.grid_columnconfigure((0,2),weight=1)
self.modal_message_label = CTkLabel(
self.modal_message_label_wrapper,
textvariable=self._view_variable.VAR_MESSAGE_CONFIRMATION_MODAL,
height=0,
corner_radius=0,
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.MESSAGE_FONT_SIZE, weight="normal"),
anchor="w",
text_color=self.settings.ctm.MESSAGE_TEXT_COLOR,
)
self.modal_message_label.grid(row=1, column=1)
self.modal_buttons_container = CTkFrame(self.modal_contents_wrapper, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
self.modal_buttons_container.grid(row=2, column=0, sticky="nsew")
self.modal_buttons_container.grid_rowconfigure((0,2),weight=1)
self.modal_buttons_container.grid_columnconfigure(0,weight=1)
self.modal_buttons_wrapper = CTkFrame(self.modal_buttons_container, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
self.modal_buttons_wrapper.grid(row=1, column=0, sticky="ew")
self.modal_buttons_wrapper.grid_columnconfigure(1, weight=1, minsize=self.settings.uism.BUTTONS_BETWEEN_PADDING)
self.modal_buttons_wrapper.grid_columnconfigure((0,2), weight=0, uniform="button_wrapper")
self.deny_button = CTkFrame(self.modal_buttons_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.DENY_BUTTON_BG_COLOR, cursor="hand2")
self.deny_button.grid(row=0, column=0, sticky="ew")
self.deny_button.grid_columnconfigure(0, weight=1)
self.deny_button_label_wrapper = CTkFrame(self.deny_button, corner_radius=0, fg_color=self.settings.ctm.DENY_BUTTON_BG_COLOR)
self.deny_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.BUTTONS_IPADX, pady=self.settings.uism.BUTTONS_IPADY, sticky="ew")
self.deny_button_label_wrapper.grid_columnconfigure((0,2), weight=1)
self.deny_button_label_wrapper.grid_columnconfigure(0, weight=1)
self.deny_button_label = CTkLabel(
self.deny_button_label_wrapper,
textvariable=self._view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON,
height=0,
corner_radius=0,
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE, weight="normal"),
anchor="w",
text_color=self.settings.ctm.CONFIRMATION_BUTTONS_TEXT_COLOR,
)
self.deny_button_label.grid(row=0, column=1)
bindButtonFunctionAndColor(
target_widgets=[
self.deny_button,
self.deny_button_label_wrapper,
self.deny_button_label,
],
enter_color=settings.ctm.DENY_BUTTON_HOVERED_BG_COLOR,
leave_color=settings.ctm.DENY_BUTTON_BG_COLOR,
clicked_color=settings.ctm.DENY_BUTTON_CLICKED_BG_COLOR,
buttonReleasedFunction=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_DENY_UPDATE),
)
self.accept_button = CTkFrame(self.modal_buttons_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR, cursor="hand2")
self.accept_button.grid(row=0, column=2, sticky="ew")
self.accept_button.grid_columnconfigure(0, weight=1)
self.accept_button_label_wrapper = CTkFrame(self.accept_button, corner_radius=0, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR)
self.accept_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.BUTTONS_IPADX, pady=self.settings.uism.BUTTONS_IPADY, sticky="ew")
self.accept_button_label_wrapper.grid_columnconfigure((0,2), weight=1)
self.accept_button_label = CTkLabel(
self.accept_button_label_wrapper,
textvariable=self._view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON,
height=0,
corner_radius=0,
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE, weight="normal"),
anchor="w",
text_color=self.settings.ctm.CONFIRMATION_BUTTONS_TEXT_COLOR,
)
self.accept_button_label.grid(row=0, column=1)
bindButtonFunctionAndColor(
target_widgets=[
self.accept_button,
self.accept_button_label_wrapper,
self.accept_button_label,
],
enter_color=settings.ctm.ACCEPT_BUTTON_HOVERED_BG_COLOR,
leave_color=settings.ctm.ACCEPT_BUTTON_BG_COLOR,
clicked_color=settings.ctm.ACCEPT_BUTTON_CLICKED_BG_COLOR,
buttonReleasedFunction=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_ACCEPT_UPDATE),
)
def hide_buttons(self):
self.modal_buttons_wrapper.grid_remove()
def show(self):
self.attributes("-alpha", 0)
self.deiconify()
self.focus_set()
setGeometryToCenterOfTheWidget(
attach_widget=self.attach_window,
target_widget=self
)
fadeInAnimation(self, steps=5, interval=0.005, max_alpha=1)
def hide(self):
self.withdraw()

View File

@@ -50,3 +50,7 @@ class _CreateWindowCover(CTkToplevel):
self.height_new = self.attach_window.winfo_height()
self.geometry("{}x{}+{}+{}".format(self.width_new, self.height_new, self.x_pos, self.y_pos))
fadeInAnimation(self, steps=5, interval=0.005, max_alpha=0.5)
def hide(self):
self.withdraw()

View File

@@ -11,17 +11,17 @@ class ConfigWindow(CTkToplevel):
super().__init__()
self.withdraw()
self.settings = settings
self._view_variable = view_variable
# configure window
self.after(200, lambda: self.iconbitmap(getImagePath("vrct_logo_mark_black.ico")))
self.geometry(f"{settings.uism.DEFAULT_WIDTH}x{settings.uism.DEFAULT_HEIGHT}")
self.geometry(f"{self.settings.uism.DEFAULT_WIDTH}x{self.settings.uism.DEFAULT_HEIGHT}")
self.configure(fg_color="#ff7f50")
self.protocol("WM_DELETE_WINDOW", vrct_gui._closeConfigWindow)
self.protocol("WM_DELETE_WINDOW", self._view_variable.CALLBACK_CLICKED_CLOSE_CONFIG_WINDOW_BUTTON)
self.settings = settings
self._view_variable = view_variable
self.title(self._view_variable.VAR_CONFIG_WINDOW_TITLE.get())
# When the configuration window's compact mode is turned on, it will call `grid_remove()` on each widget appended to this array. In the opposite case, `grid()` will be called.

View File

@@ -1,6 +1,7 @@
from customtkinter import CTkFrame, CTkLabel, CTkImage
from ...ui_utils import bindButtonFunctionAndColor
from utils import callFunctionIfCallable
from ._create_sidebar import createSidebarFeatures, createSidebarLanguagesSettings
@@ -59,5 +60,5 @@ def createSidebar(settings, main_window, view_variable):
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,
buttonReleasedFunction=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_CLICKED_OPEN_CONFIG_WINDOW_BUTTON),
)

View File

@@ -7,6 +7,7 @@ class ColorThemeManager():
self.selectable_language_window = SimpleNamespace()
self.main_window_cover = SimpleNamespace()
self.error_message_window = SimpleNamespace()
self.update_confirmation_modal = SimpleNamespace()
# old one. But leave it here for now.
# self.PRIMARY_100_COLOR = "#c4eac1"
@@ -26,6 +27,7 @@ class ColorThemeManager():
self.PRIMARY_200_COLOR = "#8acac0"
self.PRIMARY_300_COLOR = "#61b4a7"
self.PRIMARY_400_COLOR = "#48a495"
self.PRIMARY_450_COLOR = "#429c8c"
self.PRIMARY_500_COLOR = "#3b9483"
self.PRIMARY_600_COLOR = "#368777"
self.PRIMARY_650_COLOR = "#347f6f"
@@ -42,7 +44,7 @@ class ColorThemeManager():
self.DARK_450_COLOR = "#b8b9bd"
self.DARK_500_COLOR = "#a9aaae"
self.DARK_600_COLOR = "#7f8084"
# self.DARK_650_COLOR = "#75767a"
self.DARK_650_COLOR = "#75767a"
self.DARK_700_COLOR = "#6a6c6f"
self.DARK_725_COLOR = "#636467"
self.DARK_750_COLOR = "#5b5c5f"
@@ -216,6 +218,19 @@ class ColorThemeManager():
self.main_window_cover.TEXT_COLOR = self.LIGHT_100_COLOR
self.update_confirmation_modal.MESSAGE_TEXT_COLOR = self.LIGHT_100_COLOR
self.update_confirmation_modal.FAKE_BORDER_COLOR = self.DARK_600_COLOR
self.update_confirmation_modal.BG_COLOR = self.DARK_800_COLOR
self.update_confirmation_modal.CONFIRMATION_BUTTONS_TEXT_COLOR = self.LIGHT_100_COLOR
self.update_confirmation_modal.ACCEPT_BUTTON_BG_COLOR = self.PRIMARY_600_COLOR
self.update_confirmation_modal.ACCEPT_BUTTON_HOVERED_BG_COLOR = self.PRIMARY_450_COLOR
self.update_confirmation_modal.ACCEPT_BUTTON_CLICKED_BG_COLOR = self.PRIMARY_750_COLOR
self.update_confirmation_modal.DENY_BUTTON_BG_COLOR = self.DARK_750_COLOR
self.update_confirmation_modal.DENY_BUTTON_HOVERED_BG_COLOR = self.DARK_700_COLOR
self.update_confirmation_modal.DENY_BUTTON_CLICKED_BG_COLOR = self.DARK_825_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

View File

@@ -10,6 +10,7 @@ class UiScalingManager():
self.selectable_language_window = SimpleNamespace()
self.main_window_cover = SimpleNamespace()
self.error_message_window = SimpleNamespace()
self.update_confirmation_modal = SimpleNamespace()
self._calculatedUiSizes()
@@ -142,6 +143,18 @@ class UiScalingManager():
self.main_window_cover.TEXT_FONT_SIZE = self._calculateUiSize(20)
self.update_confirmation_modal.FAKE_BORDER_SIZE = self._calculateUiSize(1, is_allowed_odd=True)
self.update_confirmation_modal.CONTENTS_WRAPPER = self._calculateUiSize(20)
self.update_confirmation_modal.MARGIN_BETWEEN_MESSAGE_AND_BUTTONS = self._calculateUiSize(40)
self.update_confirmation_modal.MESSAGE_FONT_SIZE = self._calculateUiSize(20)
self.update_confirmation_modal.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE = self._calculateUiSize(18)
self.update_confirmation_modal.BUTTONS_BETWEEN_PADDING = self._calculateUiSize(100)
self.update_confirmation_modal.BUTTONS_CORNER_RADIUS = self._calculateUiSize(6)
self.update_confirmation_modal.BUTTONS_IPADX = self._calculateUiSize(10)
self.update_confirmation_modal.BUTTONS_IPADY = self._calculateUiSize(6)
# Config Window
self.config_window.DEFAULT_WIDTH = self._calculateUiSize(1080)
self.config_window.DEFAULT_HEIGHT = self._calculateUiSize(680)

View File

@@ -225,6 +225,22 @@ def setGeometryToCenterOfScreen(root_widget):
root_widget.geometry(str(geometry_width)+"x"+str(geometry_height)+"+"+str((sw-geometry_width)//2)+"+"+str((sh-geometry_height)//2))
def setGeometryToCenterOfTheWidget(attach_widget, target_widget):
target_widget.update()
target_widget.update()
current_window_x = attach_widget.winfo_rootx()
current_window_y = attach_widget.winfo_rooty()
current_window_width = attach_widget.winfo_width()
current_window_height = attach_widget.winfo_height()
desired_window_width = target_widget.winfo_width()
desired_window_height = target_widget.winfo_height()
desired_window_x = int((current_window_x + current_window_width / 2) - (desired_window_width / 2))
desired_window_y = int((current_window_y + current_window_height / 2) - (desired_window_height / 2))
target_widget.geometry(str(desired_window_width) + "x" + str(desired_window_height) + "+" + str(desired_window_x) + "+" + str(desired_window_y))
def fadeInAnimation(root_widget, steps:int=10, interval:float=0.1, max_alpha:float=1):
alpha_steps = 100
alpha_steps*=max_alpha

View File

@@ -7,6 +7,7 @@ from ._CreateErrorWindow import _CreateErrorWindow
from ._CreateDropdownMenuWindow import _CreateDropdownMenuWindow
from ._changeMainWindowWidgetsStatus import _changeMainWindowWidgetsStatus
from ._changeConfigWindowWidgetsStatus import _changeConfigWindowWidgetsStatus
from ._CreateConfirmationModal import _CreateConfirmationModal
from ._printToTextbox import _printToTextbox
from .main_window import createMainWindowWidgets
@@ -113,9 +114,15 @@ class VRCT_GUI(CTk):
message_bg_color=self.settings.config_window.ctm.SB__ERROR_MESSAGE_BG_COLOR,
message_text_color=self.settings.config_window.ctm.SB__ERROR_MESSAGE_TEXT_COLOR,
)
self.update_confirmation_modal = _CreateConfirmationModal(
attach_window=self.toplevel_wrapper,
settings=self.settings.update_confirmation_modal,
view_variable=self._view_variable
)
# self.update()
# self.geometry("{}x{}".format(self.winfo_width(), self.winfo_height()))
@@ -129,9 +136,7 @@ class VRCT_GUI(CTk):
self.destroy()
def _openConfigWindow(self, _e):
callFunctionIfCallable(self._view_variable.CALLBACK_OPEN_CONFIG_WINDOW)
def _openConfigWindow(self):
self.main_window_cover.show()
self.BIND_CONFIGURE_ADJUSTED_GEOMETRY_FUNC_ID = self.bind("<Configure>", self._adjustToMainWindowGeometry, "+")
@@ -151,11 +156,9 @@ class VRCT_GUI(CTk):
self.config_window.focus_set()
def _closeConfigWindow(self):
callFunctionIfCallable(self._view_variable.CALLBACK_CLOSE_CONFIG_WINDOW)
self.config_window.withdraw()
self.main_window_cover.withdraw()
self.main_window_cover.hide()
self.unbind("<Configure>", self.BIND_CONFIGURE_ADJUSTED_GEOMETRY_FUNC_ID)
self.unbind("<Unmap>", self.BIND_UNMAP_DETECT_MAIN_WINDOW_STATE_FUNC_ID)
self.unbind("<Map>", self.BIND_MAP_DETECT_MAIN_WINDOW_STATE_FUNC_ID)