blob: 7fed99ddf094bb57605e9fa00565e3a9e4c24420 [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)
Fred Draked038ca82000-10-23 18:31:14 +000011#
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000012# 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
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000021
22# weight/slant
23NORMAL = "normal"
Martin v. Löwis1ef23652003-06-14 21:40:04 +000024ROMAN = "roman"
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000025BOLD = "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
Martin v. Löwis1ef23652003-06-14 21:40:04 +000041 slant -- font slant: ROMAN, ITALIC
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000042 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):
Fred Draked038ca82000-10-23 18:31:14 +000055 options = []
56 for k in args:
57 options.append("-"+k)
58 return tuple(options)
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000059
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
Raymond Hettingerff41c482003-04-06 09:01:11 +000077 root.tk.call("font", "create", name, *font)
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000078 # 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"
Raymond Hettingerff41c482003-04-06 09:01:11 +000094 return Font(self._root, **self.actual())
Guido van Rossum3d16d3e1998-08-11 19:07:58 +000095
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:
Raymond Hettingerff41c482003-04-06 09:01:11 +0000112 self._call("font", "config", self.name,
113 *self._set(options))
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000114 else:
115 return self._mkdict(
116 self._split(self._call("font", "config", self.name))
117 )
118
119 configure = config
Fred Draked038ca82000-10-23 18:31:14 +0000120
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000121 def measure(self, text):
122 "Return text width"
Eric S. Raymondfc170b12001-02-09 11:51:27 +0000123 return int(self._call("font", "measure", self.name, text))
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000124
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:
Eric S. Raymondfc170b12001-02-09 11:51:27 +0000132 return int(
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000133 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):
Eric S. Raymondfc170b12001-02-09 11:51:27 +0000139 options[res[i][1:]] = int(res[i+1])
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000140 return options
141
142def families(root=None):
143 "Get font families (as a tuple)"
144 if not root:
145 root = Tkinter._default_root
Fred Draked038ca82000-10-23 18:31:14 +0000146 return root.tk.splitlist(root.tk.call("font", "families"))
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000147
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
Fred Draked038ca82000-10-23 18:31:14 +0000156
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000157if __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)
Fred Draked038ca82000-10-23 18:31:14 +0000189
Guido van Rossum3d16d3e1998-08-11 19:07:58 +0000190 w.config(font=fb)
191
192 Tkinter.mainloop()