2021-03-04 20:27:46 +03:00
|
|
|
import sys
|
2022-01-07 22:54:45 +03:00
|
|
|
import tkinter
|
2021-07-13 12:23:34 +03:00
|
|
|
from distutils.version import StrictVersion as Version
|
|
|
|
import darkdetect
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2021-07-13 12:23:34 +03:00
|
|
|
if Version(darkdetect.__version__) < Version("0.3.1"):
|
|
|
|
sys.stderr.write("WARNING: You have to update the darkdetect library: pip3 install --upgrade darkdetect\n")
|
|
|
|
if sys.platform != "darwin":
|
|
|
|
exit()
|
2021-03-06 15:47:49 +03:00
|
|
|
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-02-22 16:36:36 +03:00
|
|
|
class AppearanceModeTracker:
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
callback_list = []
|
|
|
|
root_tk_list = []
|
|
|
|
update_loop_running = False
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
appearance_mode_set_by = "system"
|
|
|
|
appearance_mode = 0 # Light (standard)
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
@classmethod
|
|
|
|
def init_appearance_mode(cls):
|
|
|
|
if cls.appearance_mode_set_by == "system":
|
|
|
|
new_appearance_mode = cls.detect_appearance_mode()
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if new_appearance_mode != cls.appearance_mode:
|
|
|
|
cls.appearance_mode = new_appearance_mode
|
|
|
|
cls.update_callbacks()
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
@classmethod
|
|
|
|
def add(cls, callback, widget=None):
|
|
|
|
cls.callback_list.append(callback)
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if widget is not None:
|
|
|
|
root_tk = cls.get_tk_root_of_widget(widget)
|
|
|
|
if root_tk not in cls.root_tk_list:
|
|
|
|
cls.root_tk_list.append(root_tk)
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if not cls.update_loop_running:
|
|
|
|
root_tk.after(500, cls.update)
|
|
|
|
cls.update_loop_running = True
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-02-23 00:38:40 +03:00
|
|
|
@classmethod
|
|
|
|
def remove(cls, callback):
|
|
|
|
cls.callback_list.remove(callback)
|
|
|
|
|
2021-03-04 20:27:46 +03:00
|
|
|
@staticmethod
|
|
|
|
def detect_appearance_mode():
|
2021-07-13 12:23:34 +03:00
|
|
|
try:
|
|
|
|
if darkdetect.theme() == "Dark":
|
|
|
|
return 1 # Dark
|
|
|
|
else:
|
2021-03-04 20:27:46 +03:00
|
|
|
return 0 # Light
|
2021-07-13 12:23:34 +03:00
|
|
|
except NameError:
|
2021-03-04 20:27:46 +03:00
|
|
|
return 0 # Light
|
|
|
|
|
2022-02-23 00:38:40 +03:00
|
|
|
@classmethod
|
|
|
|
def get_tk_root_of_widget(cls, widget):
|
|
|
|
current_widget = widget
|
|
|
|
|
|
|
|
while isinstance(current_widget, tkinter.Tk) is False:
|
|
|
|
current_widget = current_widget.master
|
|
|
|
|
|
|
|
return current_widget
|
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
@classmethod
|
|
|
|
def update_callbacks(cls):
|
|
|
|
if cls.appearance_mode == 0:
|
|
|
|
for callback in cls.callback_list:
|
|
|
|
try:
|
|
|
|
callback("Light")
|
|
|
|
except Exception:
|
|
|
|
continue
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
elif cls.appearance_mode == 1:
|
|
|
|
for callback in cls.callback_list:
|
|
|
|
try:
|
|
|
|
callback("Dark")
|
|
|
|
except Exception:
|
|
|
|
continue
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
@classmethod
|
|
|
|
def update(cls):
|
|
|
|
if cls.appearance_mode_set_by == "system":
|
|
|
|
new_appearance_mode = cls.detect_appearance_mode()
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if new_appearance_mode != cls.appearance_mode:
|
|
|
|
cls.appearance_mode = new_appearance_mode
|
|
|
|
cls.update_callbacks()
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
# find an existing tkinter.Tk object for the next call of .after()
|
|
|
|
for root_tk in cls.root_tk_list:
|
|
|
|
try:
|
|
|
|
root_tk.after(200, cls.update)
|
|
|
|
return
|
|
|
|
except Exception:
|
|
|
|
continue
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
cls.update_loop_running = False
|
2021-03-04 20:27:46 +03:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_mode(cls):
|
|
|
|
return cls.appearance_mode
|
|
|
|
|
|
|
|
@classmethod
|
2022-01-07 22:54:45 +03:00
|
|
|
def set_appearance_mode(cls, mode_string):
|
2021-03-04 20:27:46 +03:00
|
|
|
if mode_string.lower() == "dark":
|
2022-01-07 22:54:45 +03:00
|
|
|
cls.appearance_mode_set_by = "user"
|
|
|
|
new_appearance_mode = 1
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if new_appearance_mode != cls.appearance_mode:
|
|
|
|
cls.appearance_mode = new_appearance_mode
|
|
|
|
cls.update_callbacks()
|
2021-03-04 20:27:46 +03:00
|
|
|
|
|
|
|
elif mode_string.lower() == "light":
|
2022-01-07 22:54:45 +03:00
|
|
|
cls.appearance_mode_set_by = "user"
|
|
|
|
new_appearance_mode = 0
|
2021-03-04 20:27:46 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
if new_appearance_mode != cls.appearance_mode:
|
|
|
|
cls.appearance_mode = new_appearance_mode
|
|
|
|
cls.update_callbacks()
|
2022-01-02 00:16:06 +03:00
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
elif mode_string.lower() == "system":
|
|
|
|
cls.appearance_mode_set_by = "system"
|
2021-03-04 20:27:46 +03:00
|
|
|
|
|
|
|
|
2022-01-07 22:54:45 +03:00
|
|
|
AppearanceModeTracker.init_appearance_mode()
|