ctk_font.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from tkinter.font import Font
  2. import copy
  3. from typing import List, Callable, Tuple, Optional
  4. try:
  5. from typing import Literal
  6. except ImportError:
  7. from typing_extensions import Literal
  8. from ..theme import ThemeManager
  9. class CTkFont(Font):
  10. """
  11. Font object with size in pixel, independent of scaling.
  12. To get scaled tuple representation use create_scaled_tuple() method.
  13. family The font family name as a string.
  14. size The font height as an integer in pixel.
  15. weight 'bold' for boldface, 'normal' for regular weight.
  16. slant 'italic' for italic, 'roman' for unslanted.
  17. underline 1 for underlined text, 0 for normal.
  18. overstrike 1 for overstruck text, 0 for normal.
  19. Tkinter Font: https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/fonts.html
  20. """
  21. def __init__(self,
  22. family: Optional[str] = None,
  23. size: Optional[int] = None,
  24. weight: Literal["normal", "bold"] = None,
  25. slant: Literal["italic", "roman"] = "roman",
  26. underline: bool = False,
  27. overstrike: bool = False):
  28. self._size_configure_callback_list: List[Callable] = []
  29. self._size = ThemeManager.theme["CTkFont"]["size"] if size is None else size
  30. super().__init__(family=ThemeManager.theme["CTkFont"]["family"] if family is None else family,
  31. size=-abs(self._size),
  32. weight=ThemeManager.theme["CTkFont"]["weight"] if weight is None else weight,
  33. slant=slant,
  34. underline=underline,
  35. overstrike=overstrike)
  36. self._family = super().cget("family")
  37. self._tuple_style_string = f"{super().cget('weight')} {slant} {'underline' if underline else ''} {'overstrike' if overstrike else ''}"
  38. def add_size_configure_callback(self, callback: Callable):
  39. """ add function, that gets called when font got configured """
  40. self._size_configure_callback_list.append(callback)
  41. def remove_size_configure_callback(self, callback: Callable):
  42. """ remove function, that gets called when font got configured """
  43. try:
  44. self._size_configure_callback_list.remove(callback)
  45. except ValueError:
  46. pass
  47. def create_scaled_tuple(self, font_scaling: float) -> Tuple[str, int, str]:
  48. """ return scaled tuple representation of font in the form (family: str, size: int, style: str)"""
  49. return self._family, round(-abs(self._size) * font_scaling), self._tuple_style_string
  50. def config(self, *args, **kwargs):
  51. raise AttributeError("'config' is not implemented for CTk widgets. For consistency, always use 'configure' instead.")
  52. def configure(self, **kwargs):
  53. if "size" in kwargs:
  54. self._size = kwargs.pop("size")
  55. super().configure(size=-abs(self._size))
  56. if "family" in kwargs:
  57. super().configure(family=kwargs.pop("family"))
  58. self._family = super().cget("family")
  59. super().configure(**kwargs)
  60. # update style string for create_scaled_tuple() method
  61. self._tuple_style_string = f"{super().cget('weight')} {super().cget('slant')} {'underline' if super().cget('underline') else ''} {'overstrike' if super().cget('overstrike') else ''}"
  62. # call all functions registered with add_size_configure_callback()
  63. for callback in self._size_configure_callback_list:
  64. callback()
  65. def cget(self, attribute_name: str) -> any:
  66. if attribute_name == "size":
  67. return self._size
  68. if attribute_name == "family":
  69. return self._family
  70. else:
  71. return super().cget(attribute_name)
  72. def copy(self) -> "CTkFont":
  73. return copy.deepcopy(self)