2022-02-23 00:38:40 +03:00
|
|
|
import sys
|
2022-02-28 02:35:52 +03:00
|
|
|
import os
|
|
|
|
import json
|
2022-02-23 00:38:40 +03:00
|
|
|
|
|
|
|
|
|
|
|
class CTkThemeManager:
|
|
|
|
|
2022-02-28 02:35:52 +03:00
|
|
|
theme = {} # contains all the theme data
|
2022-03-02 02:53:58 +03:00
|
|
|
built_in_themes = ["blue", "green", "dark-blue"]
|
2022-02-28 02:35:52 +03:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def load_theme(cls, theme_name_or_path: str):
|
|
|
|
script_directory = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
|
|
if theme_name_or_path in cls.built_in_themes:
|
|
|
|
with open(os.path.join(script_directory, "assets", "themes", f"{theme_name_or_path}.json"), "r") as f:
|
|
|
|
cls.theme = json.load(f)
|
|
|
|
else:
|
|
|
|
with open(theme_name_or_path, "r") as f:
|
|
|
|
cls.theme = json.load(f)
|
|
|
|
|
|
|
|
if sys.platform == "darwin":
|
|
|
|
cls.theme["text"] = cls.theme["text"]["macOS"]
|
|
|
|
elif sys.platform.startswith("win"):
|
|
|
|
cls.theme["text"] = cls.theme["text"]["Windows"]
|
|
|
|
else:
|
|
|
|
cls.theme["text"] = cls.theme["text"]["Linux"]
|
2022-02-23 00:38:40 +03:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def single_color(color, appearance_mode: int) -> str:
|
|
|
|
""" color can be either a single hex color string or a color name or it can be a
|
|
|
|
tuple color with (light_color, dark_color). The functions then returns
|
|
|
|
always a single color string """
|
|
|
|
|
2022-02-28 02:35:52 +03:00
|
|
|
if type(color) == tuple or type(color) == list:
|
2022-02-23 00:38:40 +03:00
|
|
|
return color[appearance_mode]
|
|
|
|
else:
|
|
|
|
return color
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def rgb2hex(rgb_color: tuple) -> str:
|
|
|
|
return "#{:02x}{:02x}{:02x}".format(round(rgb_color[0]), round(rgb_color[1]), round(rgb_color[2]))
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def hex2rgb(hex_color: str) -> tuple:
|
|
|
|
return tuple(int(hex_color.strip("#")[i:i+2], 16) for i in (0, 2, 4))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def linear_blend(cls, color_1: str, color_2: str, blend_factor: float) -> str:
|
|
|
|
""" Blends two hex colors linear, where blend_factor of 0
|
|
|
|
results in color_1 and blend_factor of 1 results in color_2. """
|
|
|
|
|
|
|
|
if color_1 is None or color_2 is None:
|
|
|
|
return None
|
|
|
|
|
|
|
|
rgb_1 = cls.hex2rgb(color_1)
|
|
|
|
rgb_2 = cls.hex2rgb(color_2)
|
|
|
|
|
|
|
|
new_rgb = (rgb_1[0] + (rgb_2[0] - rgb_1[0]) * blend_factor,
|
|
|
|
rgb_1[1] + (rgb_2[1] - rgb_1[1]) * blend_factor,
|
|
|
|
rgb_1[2] + (rgb_2[2] - rgb_1[2]) * blend_factor)
|
|
|
|
|
|
|
|
return cls.rgb2hex(new_rgb)
|
|
|
|
|
2022-03-10 04:12:30 +03:00
|
|
|
@classmethod
|
2022-04-10 20:56:42 +03:00
|
|
|
def multiply_hex_color(cls, hex_color: str, factor: float = 1.0) -> str:
|
2022-02-23 00:38:40 +03:00
|
|
|
try:
|
|
|
|
rgb_color = CTkThemeManager.hex2rgb(hex_color)
|
2022-03-10 04:12:30 +03:00
|
|
|
dark_rgb_color = (min(255, rgb_color[0] * factor),
|
|
|
|
min(255, rgb_color[1] * factor),
|
|
|
|
min(255, rgb_color[2] * factor))
|
2022-02-23 00:38:40 +03:00
|
|
|
return CTkThemeManager.rgb2hex(dark_rgb_color)
|
|
|
|
except Exception as err:
|
2022-03-10 04:12:30 +03:00
|
|
|
# sys.stderr.write("ERROR (CTkColorManager): failed to darken the following color: " + str(hex_color) + " " + str(err))
|
2022-02-23 00:38:40 +03:00
|
|
|
return hex_color
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def set_main_color(cls, main_color, main_color_hover):
|
|
|
|
cls.MAIN_COLOR = main_color
|
|
|
|
cls.MAIN_HOVER_COLOR = main_color_hover
|
|
|
|
|
|
|
|
|
2022-04-09 20:37:07 +03:00
|
|
|
CTkThemeManager.load_theme("blue") # standard theme
|