mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
changeed driectory structure, moved scaling and appearance mode functionality to super classes
This commit is contained in:
0
customtkinter/windows/widgets/font/__init__.py
Normal file
0
customtkinter/windows/widgets/font/__init__.py
Normal file
80
customtkinter/windows/widgets/font/ctk_font.py
Normal file
80
customtkinter/windows/widgets/font/ctk_font.py
Normal file
@ -0,0 +1,80 @@
|
||||
from tkinter.font import Font
|
||||
import copy
|
||||
from typing import List, Callable, Tuple
|
||||
|
||||
from ..theme.theme_manager import ThemeManager
|
||||
|
||||
|
||||
class CTkFont(Font):
|
||||
"""
|
||||
Font object with size in pixel, independent of scaling.
|
||||
To get scaled tuple representation use create_scaled_tuple() method.
|
||||
|
||||
family The font family name as a string.
|
||||
size The font height as an integer in pixel.
|
||||
weight 'bold' for boldface, 'normal' for regular weight.
|
||||
slant 'italic' for italic, 'roman' for unslanted.
|
||||
underline 1 for underlined text, 0 for normal.
|
||||
overstrike 1 for overstruck text, 0 for normal.
|
||||
|
||||
Tkinter Font: https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/fonts.html
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
family: str = "default_theme",
|
||||
size: int = "default_theme",
|
||||
weight: str = "normal",
|
||||
slant: str = "roman",
|
||||
underline: bool = False,
|
||||
overstrike: bool = False):
|
||||
|
||||
self._size_configure_callback_list: List[Callable] = []
|
||||
|
||||
self._family = family
|
||||
self._size = ThemeManager.theme["text"]["size"] if size == "default_theme" else size
|
||||
self._tuple_style_string = f"{weight} {slant} {'underline' if underline else ''} {'overstrike' if overstrike else ''}"
|
||||
|
||||
super().__init__(family=ThemeManager.theme["text"]["font"] if family == "default_theme" else family,
|
||||
size=-abs(self._size),
|
||||
weight=weight,
|
||||
slant=slant,
|
||||
underline=underline,
|
||||
overstrike=overstrike)
|
||||
|
||||
def add_size_configure_callback(self, callback: Callable):
|
||||
""" add function, that gets called when font got configured """
|
||||
self._size_configure_callback_list.append(callback)
|
||||
|
||||
def remove_size_configure_callback(self, callback: Callable):
|
||||
""" remove function, that gets called when font got configured """
|
||||
self._size_configure_callback_list.remove(callback)
|
||||
|
||||
def create_scaled_tuple(self, font_scaling: float) -> Tuple[str, int, str]:
|
||||
""" return scaled tuple representation of font in the form (family: str, size: int, style: str)"""
|
||||
return self._family, round(self._size * font_scaling), self._tuple_style_string
|
||||
|
||||
def config(self, *args, **kwargs):
|
||||
raise AttributeError("'config' is not implemented for CTk widgets. For consistency, always use 'configure' instead.")
|
||||
|
||||
def configure(self, **kwargs):
|
||||
if "size" in kwargs:
|
||||
self._size = kwargs.pop("size")
|
||||
super().configure(size=-abs(self._size))
|
||||
|
||||
super().configure(**kwargs)
|
||||
|
||||
# update style string for create_scaled_tuple() method
|
||||
self._tuple_style_string = f"{super().cget('weight')} {super().cget('slant')} {'underline' if super().cget('underline') else ''} {'overstrike' if super().cget('overstrike') else ''}"
|
||||
|
||||
# call all functions registered with add_size_configure_callback()
|
||||
for callback in self._size_configure_callback_list:
|
||||
callback()
|
||||
|
||||
def cget(self, attribute_name: str) -> any:
|
||||
if attribute_name == "size":
|
||||
return self._size
|
||||
else:
|
||||
return super().cget(attribute_name)
|
||||
|
||||
def copy(self) -> "CTkFont":
|
||||
return copy.deepcopy(self)
|
66
customtkinter/windows/widgets/font/font_manager.py
Normal file
66
customtkinter/windows/widgets/font/font_manager.py
Normal file
@ -0,0 +1,66 @@
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
from typing import Union
|
||||
|
||||
|
||||
class FontManager:
|
||||
|
||||
linux_font_path = "~/.fonts/"
|
||||
|
||||
@classmethod
|
||||
def init_font_manager(cls):
|
||||
# Linux
|
||||
if sys.platform.startswith("linux"):
|
||||
try:
|
||||
if not os.path.isdir(os.path.expanduser(cls.linux_font_path)):
|
||||
os.mkdir(os.path.expanduser(cls.linux_font_path))
|
||||
return True
|
||||
except Exception as err:
|
||||
sys.stderr.write("FontManager error: " + str(err) + "\n")
|
||||
return False
|
||||
|
||||
# other platforms
|
||||
else:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def windows_load_font(cls, font_path: Union[str, bytes], private: bool = True, enumerable: bool = False) -> bool:
|
||||
""" Function taken from: https://stackoverflow.com/questions/11993290/truly-custom-font-in-tkinter/30631309#30631309 """
|
||||
|
||||
from ctypes import windll, byref, create_unicode_buffer, create_string_buffer
|
||||
|
||||
FR_PRIVATE = 0x10
|
||||
FR_NOT_ENUM = 0x20
|
||||
|
||||
if isinstance(font_path, bytes):
|
||||
path_buffer = create_string_buffer(font_path)
|
||||
add_font_resource_ex = windll.gdi32.AddFontResourceExA
|
||||
elif isinstance(font_path, str):
|
||||
path_buffer = create_unicode_buffer(font_path)
|
||||
add_font_resource_ex = windll.gdi32.AddFontResourceExW
|
||||
else:
|
||||
raise TypeError('font_path must be of type bytes or str')
|
||||
|
||||
flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0)
|
||||
num_fonts_added = add_font_resource_ex(byref(path_buffer), flags, 0)
|
||||
return bool(min(num_fonts_added, 1))
|
||||
|
||||
@classmethod
|
||||
def load_font(cls, font_path: str) -> bool:
|
||||
# Windows
|
||||
if sys.platform.startswith("win"):
|
||||
return cls.windows_load_font(font_path, private=True, enumerable=False)
|
||||
|
||||
# Linux
|
||||
elif sys.platform.startswith("linux"):
|
||||
try:
|
||||
shutil.copy(font_path, os.path.expanduser(cls.linux_font_path))
|
||||
return True
|
||||
except Exception as err:
|
||||
sys.stderr.write("FontManager error: " + str(err) + "\n")
|
||||
return False
|
||||
|
||||
# macOS and others
|
||||
else:
|
||||
return False
|
Reference in New Issue
Block a user