blob: 5e9abed66a028e4b899f292d21945d27d77054ee [file] [log] [blame]
Guido van Rossum3d16d3e1998-08-11 19:07:58 +00001#
2# Tkinter
3# $Id$
4#
5# font wrapper
6#
7# written by Fredrik Lundh <fredrik@pythonware.com>, February 1998
8#
9# FIXME: should add 'displayof' option where relevant (actual, families,
10# measure, and metrics)
11#
12# Copyright (c) Secret Labs AB 1998.
13#
14# info@pythonware.com
15# http://www.pythonware.com
16#
17
18__version__ = "0.9"
19
20import Tkinter
21import string
22
23# weight/slant
24NORMAL = "normal"
25BOLD = "bold"
26ITALIC = "italic"
27
28class Font:
29
30 """Represents a named font.
31
32 Constructor options are:
33
34 font -- font specifier (name, system font, or (family, size, style)-tuple)
35
36 or any combination of
37
38 family -- font 'family', e.g. Courier, Times, Helvetica
39 size -- font size in points
40 weight -- font thickness: NORMAL, BOLD
41 slant -- font slant: NORMAL, ITALIC
42 underline -- font underlining: false (0), true (1)
43 overstrike -- font strikeout: false (0), true (1)
44 name -- name to use for this font configuration (defaults to a unique name)
45 """
46
47 def _set(self, kw):
48 options = []
49 for k, v in kw.items():
50 options.append("-"+k)
51 options.append(str(v))
52 return tuple(options)
53
54 def _get(self, args):
55 options = []
56 for k in args:
57 options.append("-"+k)
58 return tuple(options)
59
60 def _mkdict(self, args):
61 options = {}
62 for i in range(0, len(args), 2):
63 options[args[i][1:]] = args[i+1]
64 return options
65
66 def __init__(self, root=None, font=None, name=None, **options):
67 if not root:
68 root = Tkinter._default_root
69 if font:
70 # get actual settings corresponding to the given font
71 font = root.tk.splitlist(root.tk.call("font", "actual", font))
72 else:
73 font = self._set(options)
74 if not name:
75 name = "font" + str(id(self))
76 self.name = name
77 apply(root.tk.call, ("font", "create", name) + font)
78 # backlinks!
79 self._root = root
80 self._split = root.tk.splitlist
81 self._call = root.tk.call
82
83 def __str__(self):
84 return self.name
85
86 def __del__(self):
87 try:
88 self._call("font", "delete", self.name)
89 except (AttributeError, Tkinter.TclError):
90 pass
91
92 def copy(self):
93 "Return a distinct copy of the current font"
94 return apply(Font, (self._root,), self.actual())
95
96 def actual(self, option=None):
97 "Return actual font attributes"
98 if option:
99 return self._call("font", "actual", self.name, "-"+option)
100 else:
101 return self._mkdict(
102 self._split(self._call("font", "actual", self.name))
103 )
104
105 def cget(self, option):
106 "Get font attribute"
107 return self._call("font", "config", self.name, "-"+option)
108
109 def config(self, **options):
110 "Modify font attributes"
111 if options:
112 apply(self._call, ("font", "config", self.name) +
113 self._set(options))
114 else:
115 return self._mkdict(
116 self._split(self._call("font", "config", self.name))
117 )
118
119 configure = config
120
121 def measure(self, text):
122 "Return text width"
123 return string.atoi(self._call("font", "measure", self.name, text))
124
125 def metrics(self, *options):
126 """Return font metrics.
127
128 For best performance, create a dummy widget
129 using this font before calling this method."""
130
131 if options:
132 return string.atoi(
133 self._call("font", "metrics", self.name, self._get(options))
134 )
135 else:
136 res = self._split(self._call("font", "metrics", self.name))
137 options = {}
138 for i in range(0, len(res), 2):
139 options[res[i][1:]] = string.atoi(res[i+1])
140 return options
141
142def families(root=None):
143 "Get font families (as a tuple)"
144 if not root:
145 root = Tkinter._default_root
146 return root.tk.splitlist(root.tk.call("font", "families"))
147
148def names(root=None):
149 "Get names of defined fonts (as a tuple)"
150 if not root:
151 root = Tkinter._default_root
152 return root.tk.splitlist(root.tk.call("font", "names"))
153
154# --------------------------------------------------------------------
155# test stuff
156
157if __name__ == "__main__":
158
159 root = Tkinter.Tk()
160
161 # create a font
162 f = Font(family="times", size=30, weight=NORMAL)
163
164 print f.actual()
165 print f.actual("family")
166 print f.actual("weight")
167
168 print f.config()
169 print f.cget("family")
170 print f.cget("weight")
171
172 print names()
173
174 print f.measure("hello"), f.metrics("linespace")
175
176 print f.metrics()
177
178 f = Font(font=("Courier", 20, "bold"))
179 print f.measure("hello"), f.metrics("linespace")
180
181 w = Tkinter.Label(root, text="Hello, world", font=f)
182 w.pack()
183
184 w = Tkinter.Button(root, text="Quit!", command=root.destroy)
185 w.pack()
186
187 fb = Font(font=w["font"]).copy()
188 fb.config(weight=BOLD)
189
190 w.config(font=fb)
191
192 Tkinter.mainloop()