logo

oasis-root

Compiled tree of Oasis Linux based on own branch at <https://hacktivis.me/git/oasis/> git clone https://anongit.hacktivis.me/git/oasis-root.git

font.py (7000B)


  1. # Tkinter font wrapper
  2. #
  3. # written by Fredrik Lundh, February 1998
  4. #
  5. import itertools
  6. import tkinter
  7. __version__ = "0.9"
  8. __all__ = ["NORMAL", "ROMAN", "BOLD", "ITALIC",
  9. "nametofont", "Font", "families", "names"]
  10. # weight/slant
  11. NORMAL = "normal"
  12. ROMAN = "roman"
  13. BOLD = "bold"
  14. ITALIC = "italic"
  15. def nametofont(name, root=None):
  16. """Given the name of a tk named font, returns a Font representation.
  17. """
  18. return Font(name=name, exists=True, root=root)
  19. class Font:
  20. """Represents a named font.
  21. Constructor options are:
  22. font -- font specifier (name, system font, or (family, size, style)-tuple)
  23. name -- name to use for this font configuration (defaults to a unique name)
  24. exists -- does a named font by this name already exist?
  25. Creates a new named font if False, points to the existing font if True.
  26. Raises _tkinter.TclError if the assertion is false.
  27. the following are ignored if font is specified:
  28. family -- font 'family', e.g. Courier, Times, Helvetica
  29. size -- font size in points
  30. weight -- font thickness: NORMAL, BOLD
  31. slant -- font slant: ROMAN, ITALIC
  32. underline -- font underlining: false (0), true (1)
  33. overstrike -- font strikeout: false (0), true (1)
  34. """
  35. counter = itertools.count(1)
  36. def _set(self, kw):
  37. options = []
  38. for k, v in kw.items():
  39. options.append("-"+k)
  40. options.append(str(v))
  41. return tuple(options)
  42. def _get(self, args):
  43. options = []
  44. for k in args:
  45. options.append("-"+k)
  46. return tuple(options)
  47. def _mkdict(self, args):
  48. options = {}
  49. for i in range(0, len(args), 2):
  50. options[args[i][1:]] = args[i+1]
  51. return options
  52. def __init__(self, root=None, font=None, name=None, exists=False,
  53. **options):
  54. if root is None:
  55. root = tkinter._get_default_root('use font')
  56. tk = getattr(root, 'tk', root)
  57. if font:
  58. # get actual settings corresponding to the given font
  59. font = tk.splitlist(tk.call("font", "actual", font))
  60. else:
  61. font = self._set(options)
  62. if not name:
  63. name = "font" + str(next(self.counter))
  64. self.name = name
  65. if exists:
  66. self.delete_font = False
  67. # confirm font exists
  68. if self.name not in tk.splitlist(tk.call("font", "names")):
  69. raise tkinter._tkinter.TclError(
  70. "named font %s does not already exist" % (self.name,))
  71. # if font config info supplied, apply it
  72. if font:
  73. tk.call("font", "configure", self.name, *font)
  74. else:
  75. # create new font (raises TclError if the font exists)
  76. tk.call("font", "create", self.name, *font)
  77. self.delete_font = True
  78. self._tk = tk
  79. self._split = tk.splitlist
  80. self._call = tk.call
  81. def __str__(self):
  82. return self.name
  83. def __repr__(self):
  84. return f"<{self.__class__.__module__}.{self.__class__.__qualname__}" \
  85. f" object {self.name!r}>"
  86. def __eq__(self, other):
  87. if not isinstance(other, Font):
  88. return NotImplemented
  89. return self.name == other.name and self._tk == other._tk
  90. def __getitem__(self, key):
  91. return self.cget(key)
  92. def __setitem__(self, key, value):
  93. self.configure(**{key: value})
  94. def __del__(self):
  95. try:
  96. if self.delete_font:
  97. self._call("font", "delete", self.name)
  98. except Exception:
  99. pass
  100. def copy(self):
  101. "Return a distinct copy of the current font"
  102. return Font(self._tk, **self.actual())
  103. def actual(self, option=None, displayof=None):
  104. "Return actual font attributes"
  105. args = ()
  106. if displayof:
  107. args = ('-displayof', displayof)
  108. if option:
  109. args = args + ('-' + option, )
  110. return self._call("font", "actual", self.name, *args)
  111. else:
  112. return self._mkdict(
  113. self._split(self._call("font", "actual", self.name, *args)))
  114. def cget(self, option):
  115. "Get font attribute"
  116. return self._call("font", "config", self.name, "-"+option)
  117. def config(self, **options):
  118. "Modify font attributes"
  119. if options:
  120. self._call("font", "config", self.name,
  121. *self._set(options))
  122. else:
  123. return self._mkdict(
  124. self._split(self._call("font", "config", self.name)))
  125. configure = config
  126. def measure(self, text, displayof=None):
  127. "Return text width"
  128. args = (text,)
  129. if displayof:
  130. args = ('-displayof', displayof, text)
  131. return self._tk.getint(self._call("font", "measure", self.name, *args))
  132. def metrics(self, *options, **kw):
  133. """Return font metrics.
  134. For best performance, create a dummy widget
  135. using this font before calling this method."""
  136. args = ()
  137. displayof = kw.pop('displayof', None)
  138. if displayof:
  139. args = ('-displayof', displayof)
  140. if options:
  141. args = args + self._get(options)
  142. return self._tk.getint(
  143. self._call("font", "metrics", self.name, *args))
  144. else:
  145. res = self._split(self._call("font", "metrics", self.name, *args))
  146. options = {}
  147. for i in range(0, len(res), 2):
  148. options[res[i][1:]] = self._tk.getint(res[i+1])
  149. return options
  150. def families(root=None, displayof=None):
  151. "Get font families (as a tuple)"
  152. if root is None:
  153. root = tkinter._get_default_root('use font.families()')
  154. args = ()
  155. if displayof:
  156. args = ('-displayof', displayof)
  157. return root.tk.splitlist(root.tk.call("font", "families", *args))
  158. def names(root=None):
  159. "Get names of defined fonts (as a tuple)"
  160. if root is None:
  161. root = tkinter._get_default_root('use font.names()')
  162. return root.tk.splitlist(root.tk.call("font", "names"))
  163. # --------------------------------------------------------------------
  164. # test stuff
  165. if __name__ == "__main__":
  166. root = tkinter.Tk()
  167. # create a font
  168. f = Font(family="times", size=30, weight=NORMAL)
  169. print(f.actual())
  170. print(f.actual("family"))
  171. print(f.actual("weight"))
  172. print(f.config())
  173. print(f.cget("family"))
  174. print(f.cget("weight"))
  175. print(names())
  176. print(f.measure("hello"), f.metrics("linespace"))
  177. print(f.metrics(displayof=root))
  178. f = Font(font=("Courier", 20, "bold"))
  179. print(f.measure("hello"), f.metrics("linespace", displayof=root))
  180. w = tkinter.Label(root, text="Hello, world", font=f)
  181. w.pack()
  182. w = tkinter.Button(root, text="Quit!", command=root.destroy)
  183. w.pack()
  184. fb = Font(font=w["font"]).copy()
  185. fb.config(weight=BOLD)
  186. w.config(font=fb)
  187. tkinter.mainloop()