mirror of
https://github.com/python/cpython.git
synced 2024-11-26 19:34:19 +08:00
Check in another copy of tktools.py...
This commit is contained in:
parent
06981c328d
commit
de99d310cc
367
Tools/webchecker/tktools.py
Normal file
367
Tools/webchecker/tktools.py
Normal file
@ -0,0 +1,367 @@
|
||||
"""Assorted Tk-related subroutines used in Grail."""
|
||||
|
||||
|
||||
import string
|
||||
from types import *
|
||||
from Tkinter import *
|
||||
|
||||
def _clear_entry_widget(event):
|
||||
try:
|
||||
widget = event.widget
|
||||
widget.delete(0, INSERT)
|
||||
except: pass
|
||||
def install_keybindings(root):
|
||||
root.bind_class('Entry', '<Control-u>', _clear_entry_widget)
|
||||
|
||||
|
||||
def make_toplevel(master, title=None, class_=None):
|
||||
"""Create a Toplevel widget.
|
||||
|
||||
This is a shortcut for a Toplevel() instantiation plus calls to
|
||||
set the title and icon name of the widget.
|
||||
|
||||
"""
|
||||
|
||||
if class_:
|
||||
widget = Toplevel(master, class_=class_)
|
||||
else:
|
||||
widget = Toplevel(master)
|
||||
if title:
|
||||
widget.title(title)
|
||||
widget.iconname(title)
|
||||
return widget
|
||||
|
||||
def set_transient(widget, master, relx=0.5, rely=0.3, expose=1):
|
||||
"""Make an existing toplevel widget transient for a master.
|
||||
|
||||
The widget must exist but should not yet have been placed; in
|
||||
other words, this should be called after creating all the
|
||||
subwidget but before letting the user interact.
|
||||
"""
|
||||
|
||||
widget.withdraw() # Remain invisible while we figure out the geometry
|
||||
widget.transient(master)
|
||||
widget.update_idletasks() # Actualize geometry information
|
||||
if master.winfo_ismapped():
|
||||
m_width = master.winfo_width()
|
||||
m_height = master.winfo_height()
|
||||
m_x = master.winfo_rootx()
|
||||
m_y = master.winfo_rooty()
|
||||
else:
|
||||
m_width = master.winfo_screenwidth()
|
||||
m_height = master.winfo_screenheight()
|
||||
m_x = m_y = 0
|
||||
w_width = widget.winfo_reqwidth()
|
||||
w_height = widget.winfo_reqheight()
|
||||
x = m_x + (m_width - w_width) * relx
|
||||
y = m_y + (m_height - w_height) * rely
|
||||
widget.geometry("+%d+%d" % (x, y))
|
||||
if expose:
|
||||
widget.deiconify() # Become visible at the desired location
|
||||
return widget
|
||||
|
||||
|
||||
def make_scrollbars(parent, hbar, vbar, pack=1, class_=None, name=None,
|
||||
takefocus=0):
|
||||
|
||||
"""Subroutine to create a frame with scrollbars.
|
||||
|
||||
This is used by make_text_box and similar routines.
|
||||
|
||||
Note: the caller is responsible for setting the x/y scroll command
|
||||
properties (e.g. by calling set_scroll_commands()).
|
||||
|
||||
Return a tuple containing the hbar, the vbar, and the frame, where
|
||||
hbar and vbar are None if not requested.
|
||||
|
||||
"""
|
||||
if class_:
|
||||
if name: frame = Frame(parent, class_=class_, name=name)
|
||||
else: frame = Frame(parent, class_=class_)
|
||||
else:
|
||||
if name: frame = Frame(parent, name=name)
|
||||
else: frame = Frame(parent)
|
||||
|
||||
if pack:
|
||||
frame.pack(fill=BOTH, expand=1)
|
||||
|
||||
corner = None
|
||||
if vbar:
|
||||
if not hbar:
|
||||
vbar = Scrollbar(frame, takefocus=takefocus)
|
||||
vbar.pack(fill=Y, side=RIGHT)
|
||||
else:
|
||||
vbarframe = Frame(frame, borderwidth=0)
|
||||
vbarframe.pack(fill=Y, side=RIGHT)
|
||||
vbar = Scrollbar(frame, name="vbar", takefocus=takefocus)
|
||||
vbar.pack(in_=vbarframe, expand=1, fill=Y, side=TOP)
|
||||
sbwidth = vbar.winfo_reqwidth()
|
||||
corner = Frame(vbarframe, width=sbwidth, height=sbwidth)
|
||||
corner.propagate(0)
|
||||
corner.pack(side=BOTTOM)
|
||||
else:
|
||||
vbar = None
|
||||
|
||||
if hbar:
|
||||
hbar = Scrollbar(frame, orient=HORIZONTAL, name="hbar",
|
||||
takefocus=takefocus)
|
||||
hbar.pack(fill=X, side=BOTTOM)
|
||||
else:
|
||||
hbar = None
|
||||
|
||||
return hbar, vbar, frame
|
||||
|
||||
|
||||
def set_scroll_commands(widget, hbar, vbar):
|
||||
|
||||
"""Link a scrollable widget to its scroll bars.
|
||||
|
||||
The scroll bars may be empty.
|
||||
|
||||
"""
|
||||
|
||||
if vbar:
|
||||
widget['yscrollcommand'] = (vbar, 'set')
|
||||
vbar['command'] = (widget, 'yview')
|
||||
|
||||
if hbar:
|
||||
widget['xscrollcommand'] = (hbar, 'set')
|
||||
hbar['command'] = (widget, 'xview')
|
||||
|
||||
widget.vbar = vbar
|
||||
widget.hbar = hbar
|
||||
|
||||
|
||||
def make_text_box(parent, width=0, height=0, hbar=0, vbar=1,
|
||||
fill=BOTH, expand=1, wrap=WORD, pack=1,
|
||||
class_=None, name=None, takefocus=None):
|
||||
|
||||
"""Subroutine to create a text box.
|
||||
|
||||
Create:
|
||||
- a both-ways filling and expanding frame, containing:
|
||||
- a text widget on the left, and
|
||||
- possibly a vertical scroll bar on the right.
|
||||
- possibly a horizonta; scroll bar at the bottom.
|
||||
|
||||
Return the text widget and the frame widget.
|
||||
|
||||
"""
|
||||
hbar, vbar, frame = make_scrollbars(parent, hbar, vbar, pack,
|
||||
class_=class_, name=name,
|
||||
takefocus=takefocus)
|
||||
|
||||
widget = Text(frame, wrap=wrap, name="text")
|
||||
if width: widget.config(width=width)
|
||||
if height: widget.config(height=height)
|
||||
widget.pack(expand=expand, fill=fill, side=LEFT)
|
||||
|
||||
set_scroll_commands(widget, hbar, vbar)
|
||||
|
||||
return widget, frame
|
||||
|
||||
|
||||
def make_list_box(parent, width=0, height=0, hbar=0, vbar=1,
|
||||
fill=BOTH, expand=1, pack=1, class_=None, name=None,
|
||||
takefocus=None):
|
||||
|
||||
"""Subroutine to create a list box.
|
||||
|
||||
Like make_text_box().
|
||||
"""
|
||||
hbar, vbar, frame = make_scrollbars(parent, hbar, vbar, pack,
|
||||
class_=class_, name=name,
|
||||
takefocus=takefocus)
|
||||
|
||||
widget = Listbox(frame, name="listbox")
|
||||
if width: widget.config(width=width)
|
||||
if height: widget.config(height=height)
|
||||
widget.pack(expand=expand, fill=fill, side=LEFT)
|
||||
|
||||
set_scroll_commands(widget, hbar, vbar)
|
||||
|
||||
return widget, frame
|
||||
|
||||
|
||||
def make_canvas(parent, width=0, height=0, hbar=1, vbar=1,
|
||||
fill=BOTH, expand=1, pack=1, class_=None, name=None,
|
||||
takefocus=None):
|
||||
|
||||
"""Subroutine to create a canvas.
|
||||
|
||||
Like make_text_box().
|
||||
|
||||
"""
|
||||
|
||||
hbar, vbar, frame = make_scrollbars(parent, hbar, vbar, pack,
|
||||
class_=class_, name=name,
|
||||
takefocus=takefocus)
|
||||
|
||||
widget = Canvas(frame, scrollregion=(0, 0, width, height), name="canvas")
|
||||
if width: widget.config(width=width)
|
||||
if height: widget.config(height=height)
|
||||
widget.pack(expand=expand, fill=fill, side=LEFT)
|
||||
|
||||
set_scroll_commands(widget, hbar, vbar)
|
||||
|
||||
return widget, frame
|
||||
|
||||
|
||||
|
||||
def make_form_entry(parent, label, borderwidth=None):
|
||||
|
||||
"""Subroutine to create a form entry.
|
||||
|
||||
Create:
|
||||
- a horizontally filling and expanding frame, containing:
|
||||
- a label on the left, and
|
||||
- a text entry on the right.
|
||||
|
||||
Return the entry widget and the frame widget.
|
||||
|
||||
"""
|
||||
|
||||
frame = Frame(parent)
|
||||
frame.pack(fill=X)
|
||||
|
||||
label = Label(frame, text=label)
|
||||
label.pack(side=LEFT)
|
||||
|
||||
if borderwidth is None:
|
||||
entry = Entry(frame, relief=SUNKEN)
|
||||
else:
|
||||
entry = Entry(frame, relief=SUNKEN, borderwidth=borderwidth)
|
||||
entry.pack(side=LEFT, fill=X, expand=1)
|
||||
|
||||
return entry, frame
|
||||
|
||||
# This is a slightly modified version of the function above. This
|
||||
# version does the proper alighnment of labels with their fields. It
|
||||
# should probably eventually replace make_form_entry altogether.
|
||||
#
|
||||
# The one annoying bug is that the text entry field should be
|
||||
# expandable while still aligning the colons. This doesn't work yet.
|
||||
#
|
||||
def make_labeled_form_entry(parent, label, entrywidth=20, entryheight=1,
|
||||
labelwidth=0, borderwidth=None,
|
||||
takefocus=None):
|
||||
"""Subroutine to create a form entry.
|
||||
|
||||
Create:
|
||||
- a horizontally filling and expanding frame, containing:
|
||||
- a label on the left, and
|
||||
- a text entry on the right.
|
||||
|
||||
Return the entry widget and the frame widget.
|
||||
"""
|
||||
if label and label[-1] != ':': label = label + ':'
|
||||
|
||||
frame = Frame(parent)
|
||||
|
||||
label = Label(frame, text=label, width=labelwidth, anchor=E)
|
||||
label.pack(side=LEFT)
|
||||
if entryheight == 1:
|
||||
if borderwidth is None:
|
||||
entry = Entry(frame, relief=SUNKEN, width=entrywidth)
|
||||
else:
|
||||
entry = Entry(frame, relief=SUNKEN, width=entrywidth,
|
||||
borderwidth=borderwidth)
|
||||
entry.pack(side=RIGHT, expand=1, fill=X)
|
||||
frame.pack(fill=X)
|
||||
else:
|
||||
entry = make_text_box(frame, entrywidth, entryheight, 1, 1,
|
||||
takefocus=takefocus)
|
||||
frame.pack(fill=BOTH, expand=1)
|
||||
|
||||
return entry, frame, label
|
||||
|
||||
|
||||
def make_double_frame(master=None, class_=None, name=None, relief=RAISED,
|
||||
borderwidth=1):
|
||||
"""Create a pair of frames suitable for 'hosting' a dialog."""
|
||||
if name:
|
||||
if class_: frame = Frame(master, class_=class_, name=name)
|
||||
else: frame = Frame(master, name=name)
|
||||
else:
|
||||
if class_: frame = Frame(master, class_=class_)
|
||||
else: frame = Frame(master)
|
||||
top = Frame(frame, name="topframe", relief=relief,
|
||||
borderwidth=borderwidth)
|
||||
bottom = Frame(frame, name="bottomframe")
|
||||
bottom.pack(fill=X, padx='1m', pady='1m', side=BOTTOM)
|
||||
top.pack(expand=1, fill=BOTH, padx='1m', pady='1m')
|
||||
frame.pack(expand=1, fill=BOTH)
|
||||
top = Frame(top)
|
||||
top.pack(expand=1, fill=BOTH, padx='2m', pady='2m')
|
||||
|
||||
return frame, top, bottom
|
||||
|
||||
|
||||
def make_group_frame(master, name=None, label=None, fill=Y,
|
||||
side=None, expand=None, font=None):
|
||||
"""Create nested frames with a border and optional label.
|
||||
|
||||
The outer frame is only used to provide the decorative border, to
|
||||
control packing, and to host the label. The inner frame is packed
|
||||
to fill the outer frame and should be used as the parent of all
|
||||
sub-widgets. Only the inner frame is returned.
|
||||
|
||||
"""
|
||||
font = font or "-*-helvetica-medium-r-normal-*-*-100-*-*-*-*-*-*"
|
||||
outer = Frame(master, borderwidth=2, relief=GROOVE)
|
||||
outer.pack(expand=expand, fill=fill, side=side)
|
||||
if label:
|
||||
Label(outer, text=label, font=font, anchor=W).pack(fill=X)
|
||||
inner = Frame(master, borderwidth='1m', name=name)
|
||||
inner.pack(expand=1, fill=BOTH, in_=outer)
|
||||
inner.forget = outer.forget
|
||||
return inner
|
||||
|
||||
|
||||
def unify_button_widths(*buttons):
|
||||
"""Make buttons passed in all have the same width.
|
||||
|
||||
Works for labels and other widgets with the 'text' option.
|
||||
|
||||
"""
|
||||
wid = 0
|
||||
for btn in buttons:
|
||||
wid = max(wid, len(btn["text"]))
|
||||
for btn in buttons:
|
||||
btn["width"] = wid
|
||||
|
||||
|
||||
def flatten(msg):
|
||||
"""Turn a list or tuple into a single string -- recursively."""
|
||||
t = type(msg)
|
||||
if t in (ListType, TupleType):
|
||||
msg = string.join(map(flatten, msg))
|
||||
elif t is ClassType:
|
||||
msg = msg.__name__
|
||||
else:
|
||||
msg = str(msg)
|
||||
return msg
|
||||
|
||||
|
||||
def boolean(s):
|
||||
"""Test whether a string is a Tk boolean, without error checking."""
|
||||
if string.lower(s) in ('', '0', 'no', 'off', 'false'): return 0
|
||||
else: return 1
|
||||
|
||||
|
||||
def test():
|
||||
"""Test make_text_box(), make_form_entry(), flatten(), boolean()."""
|
||||
import sys
|
||||
root = Tk()
|
||||
entry, eframe = make_form_entry(root, 'Boolean:')
|
||||
text, tframe = make_text_box(root)
|
||||
def enter(event, entry=entry, text=text):
|
||||
s = boolean(entry.get()) and '\nyes' or '\nno'
|
||||
text.insert('end', s)
|
||||
entry.bind('<Return>', enter)
|
||||
entry.insert(END, flatten(sys.argv))
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
Loading…
Reference in New Issue
Block a user