Commit 18468822 authored by Guido van Rossum's avatar Guido van Rossum

Initial revision

parent 7ce61c13
#! /ufs/guido/bin/sgi/tkpython
# View a single MIME multipart message.
# Display each part as a box.
import string
from types import *
from Tkinter import *
from ScrolledText import ScrolledText
class MimeViewer:
def __init__(self, parent, title, msg):
self.title = title
self.msg = msg
self.frame = Frame(parent, {'relief': 'raised', 'bd': 2})
self.frame.packing = {'expand': 0, 'fill': 'both'}
self.button = Checkbutton(self.frame,
{'text': title,
'command': self.toggle})
self.button.pack({'anchor': 'w'})
headertext = msg.getheadertext(
lambda x: x != 'received' and x[:5] != 'x400-')
height = countlines(headertext, 4)
if height:
self.htext = ScrolledText(self.frame,
{'height': height,
'width': 80,
'wrap': 'none',
'relief': 'raised',
'bd': 2})
self.htext.packing = {'expand': 1, 'fill': 'both',
'after': self.button}
self.htext.insert('end', headertext)
else:
self.htext = Frame(self.frame,
{'relief': 'raised', 'bd': 2})
self.htext.packing = {'side': 'top',
'ipady': 2,
'fill': 'x',
'after': self.button}
body = msg.getbody()
if type(body) == StringType:
self.pad = None
height = countlines(body, 10)
if height:
self.btext = ScrolledText(self.frame,
{'height': height,
'width': 80,
'wrap': 'none',
'relief': 'raised',
'bd': 2})
self.btext.packing = {'expand': 1,
'fill': 'both'}
self.btext.insert('end', body)
else:
self.btext = None
self.parts = None
else:
self.pad = Frame(self.frame,
{'relief': 'flat', 'bd': 2})
self.pad.packing = {'side': 'left', 'ipadx': 10,
'fill': 'y', 'after': self.htext}
self.parts = []
for i in range(len(body)):
p = MimeViewer(self.frame,
'%s.%d' % (title, i+1),
body[i])
self.parts.append(p)
self.btext = None
self.collapsed = 1
def pack(self):
self.frame.pack(self.frame.packing)
def destroy(self):
self.frame.destroy()
def show(self):
if self.collapsed:
self.button.invoke()
def toggle(self):
if self.collapsed:
self.explode()
else:
self.collapse()
def collapse(self):
self.collapsed = 1
for comp in self.htext, self.btext, self.pad:
if comp:
comp.forget()
if self.parts:
for part in self.parts:
part.frame.forget()
self.frame.pack({'expand': 0})
def explode(self):
self.collapsed = 0
for comp in self.htext, self.btext, self.pad:
if comp: comp.pack(comp.packing)
if self.parts:
for part in self.parts:
part.pack()
self.frame.pack({'expand': 1})
def countlines(str, limit):
i = 0
n = 0
while n < limit:
i = string.find(str, '\n', i)
if i < 0: break
n = n+1
i = i+1
return n
def main():
import sys
import getopt
import mhlib
opts, args = getopt.getopt(sys.argv[1:], '')
for o, a in opts:
pass
message = None
folder = 'inbox'
for arg in args:
if arg[:1] == '+':
folder = arg[1:]
else:
message = string.atoi(arg)
mh = mhlib.MH()
f = mh.openfolder(folder)
if not message:
message = f.getcurrent()
m = f.openmessage(message)
root = Tk()
tk = root.tk
top = MimeViewer(root, '+%s/%d' % (folder, message), m)
top.pack()
top.show()
root.minsize(1, 1)
tk.mainloop()
if __name__ == '__main__': main()
#! /ufs/guido/bin/sgi/tkpython
# A Python function that generates dialog boxes with a text message,
# optional bitmap, and any number of buttons.
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
from Tkinter import *
def dialog(master, title, text, bitmap, default, *args):
# 1. Create the top-level window and divide it into top
# and bottom parts.
w = Toplevel(master, {'class': 'Dialog'})
w.tk.call('global', 'button')
w.title(title)
w.iconname('Dialog')
top = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'top', 'fill': 'both'}})
bot = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'bottom', 'fill': 'both'}})
# 2. Fill the top part with the bitmap and message.
msg = Message(top,
{'width': '3i',
'text': text,
'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
Pack: {'side': 'right', 'expand': 1,
'fill': 'both',
'padx': '3m', 'pady': '3m'}})
if bitmap:
bm = Label(top, {'bitmap': bitmap,
Pack: {'side': 'left',
'padx': '3m', 'pady': '3m'}})
# 3. Create a row of buttons at the bottom of the dialog.
buttons = []
i = 0
for but in args:
b = Button(bot, {'text': but,
'command': ('set', 'button', i)})
buttons.append(b)
if i == default:
bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
Pack: {'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '2m'}})
w.tk.call('raise', b)
b.pack ({'in': bd, 'side': 'left',
'padx': '2m', 'pady': '2m',
'ipadx': '2m', 'ipady': '1m'})
else:
b.pack ({'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '3m',
'ipady': '2m', 'ipady': '1m'})
i = i+1
# 4. Set up a binding for <Return>, if there's a default,
# set a grab, and claim the focus too.
if default >= 0:
w.bind('<Return>',
lambda b=buttons[default], i=default:
(b.cmd('flash'),
b.tk.call('set', 'button', i)))
oldFocus = w.tk.call('focus')
w.tk.call('grab', 'set', w)
w.tk.call('focus', w)
# 5. Wait for the user to respond, then restore the focus
# and return the index of the selected button.
w.tk.call('tkwait', 'variable', 'button')
w.tk.call('destroy', w)
w.tk.call('focus', oldFocus)
return w.tk.call('set', 'button')
# The rest is the test program.
def go():
i = dialog(mainWidget,
'Not Responding',
"The file server isn't responding right now; "
"I'll keep trying.",
'',
-1,
'OK')
print 'pressed button', i
i = dialog(mainWidget,
'File Modified',
'File "tcl.h" has been modified since '
'the last time it was saved. '
'Do you want to save it before exiting the application?',
'warning',
0,
'Save File',
'Discard Changes',
'Return To Editor')
print 'pressed button', i
def test():
import sys
global mainWidget
mainWidget = Frame()
Pack.config(mainWidget)
start = Button(mainWidget,
{'text': 'Press Here To Start', 'command': go})
start.pack()
endit = Button(mainWidget,
{'text': 'Exit',
'command': 'exit',
Pack: {'fill' : 'both'}})
mainWidget.tk.mainloop()
if __name__ == '__main__':
test()
#! /ufs/guido/bin/sgi/tkpython
# Scan MH folder, display results in window
import os
import sys
import regex
import getopt
import string
import mhlib
from Tkinter import *
from dialog import dialog
mailbox = os.environ['HOME'] + '/Mail'
def main():
global root, tk, top, mid, bot
global folderbox, foldermenu, scanbox, scanmenu, viewer
global folder, seq
global mh, mhf
# Parse command line options
folder = 'inbox'
seq = 'all'
try:
opts, args = getopt.getopt(sys.argv[1:], '')
except getopt.error, msg:
print msg
sys.exit(2)
for arg in args:
if arg[:1] == '+':
folder = arg[1:]
else:
seq = arg
# Initialize MH
mh = mhlib.MH()
mhf = mh.openfolder(folder)
# Build widget hierarchy
root = Tk()
tk = root.tk
top = Frame(root)
top.pack({'expand': 1, 'fill': 'both'})
# Build right part: folder list
right = Frame(top)
right.pack({'fill': 'y', 'side': 'right'})
folderbar = Scrollbar(right, {'relief': 'sunken', 'bd': 2})
folderbar.pack({'fill': 'y', 'side': 'right'})
folderbox = Listbox(right)
folderbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
foldermenu = Menu(root)
foldermenu.add('command',
{'label': 'Open Folder',
'command': open_folder})
foldermenu.add('separator')
foldermenu.add('command',
{'label': 'Quit',
'command': 'exit'})
foldermenu.bind('<ButtonRelease-3>', folder_unpost)
folderbox['yscrollcommand'] = (folderbar, 'set')
folderbar['command'] = (folderbox, 'yview')
folderbox.bind('<Double-1>', open_folder, 1)
folderbox.bind('<3>', folder_post)
# Build left part: scan list
left = Frame(top)
left.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
scanbar = Scrollbar(left, {'relief': 'sunken', 'bd': 2})
scanbar.pack({'fill': 'y', 'side': 'right'})
scanbox = Listbox(left, {'font': 'fixed'})
scanbox.pack({'expand': 1, 'fill': 'both', 'side': 'left'})
scanmenu = Menu(root)
scanmenu.add('command',
{'label': 'Open Message',
'command': open_message})
scanmenu.add('command',
{'label': 'Remove Message',
'command': remove_message})
scanmenu.add('command',
{'label': 'Refile Message',
'command': refile_message})
scanmenu.add('separator')
scanmenu.add('command',
{'label': 'Quit',
'command': 'exit'})
scanmenu.bind('<ButtonRelease-3>', scan_unpost)
scanbox['yscrollcommand'] = (scanbar, 'set')
scanbar['command'] = (scanbox, 'yview')
scanbox.bind('<Double-1>', open_message)
scanbox.bind('<3>', scan_post)
# Separator between middle and bottom part
rule2 = Frame(root, {'bg': 'black'})
rule2.pack({'fill': 'x'})
# Build bottom part: current message
bot = Frame(root)
bot.pack({'expand': 1, 'fill': 'both'})
#
viewer = None
# Window manager commands
root.minsize(800, 1) # Make window resizable
# Fill folderbox with text
setfolders()
# Fill scanbox with text
rescan()
# Enter mainloop
root.mainloop()
def folder_post(e):
x, y = e.x_root, e.y_root
foldermenu.post(x - 10, y - 10)
foldermenu.grab_set()
def folder_unpost(e):
tk.call('update', 'idletasks')
foldermenu.grab_release()
foldermenu.unpost()
foldermenu.invoke('active')
def scan_post(e):
x, y = e.x_root, e.y_root
scanmenu.post(x - 10, y - 10)
scanmenu.grab_set()
def scan_unpost(e):
tk.call('update', 'idletasks')
scanmenu.grab_release()
scanmenu.unpost()
scanmenu.invoke('active')
scanparser = regex.compile('^ *\([0-9]+\)')
def open_folder(*e):
global folder, mhf
sel = folderbox.curselection()
if len(sel) != 1:
if len(sel) > 1:
msg = "Please open one folder at a time"
else:
msg = "Please select a folder to open"
dialog(root, "Can't Open Folder", msg, "", 0, "OK")
return
i = sel[0]
folder = folderbox.get(i)
mhf = mh.openfolder(folder)
rescan()
def open_message(*e):
global viewer
sel = scanbox.curselection()
if len(sel) != 1:
if len(sel) > 1:
msg = "Please open one message at a time"
else:
msg = "Please select a message to open"
dialog(root, "Can't Open Message", msg, "", 0, "OK")
return
cursor = scanbox['cursor']
scanbox['cursor'] = 'watch'
tk.call('update', 'idletasks')
i = sel[0]
line = scanbox.get(i)
if scanparser.match(line) >= 0:
num = string.atoi(scanparser.group(1))
m = mhf.openmessage(num)
if viewer: viewer.destroy()
from MimeViewer import MimeViewer
viewer = MimeViewer(bot, '+%s/%d' % (folder, num), m)
viewer.pack()
viewer.show()
scanbox['cursor'] = cursor
def interestingheader(header):
return header != 'received'
def remove_message():
itop = scanbox.nearest(0)
sel = scanbox.curselection()
if not sel:
dialog(root, "No Message To Remove",
"Please select a message to remove", "", 0, "OK")
return
todo = []
for i in sel:
line = scanbox.get(i)
if scanparser.match(line) >= 0:
todo.append(string.atoi(scanparser.group(1)))
mhf.removemessages(todo)
rescan()
fixfocus(min(todo), itop)
lastrefile = ''
tofolder = None
def refile_message():
global lastrefile, tofolder
itop = scanbox.nearest(0)
sel = scanbox.curselection()
if not sel:
dialog(root, "No Message To Refile",
"Please select a message to refile", "", 0, "OK")
return
foldersel = folderbox.curselection()
if len(foldersel) != 1:
if not foldersel:
msg = "Please select a folder to refile to"
else:
msg = "Please select exactly one folder to refile to"
dialog(root, "No Folder To Refile", msg, "", 0, "OK")
return
refileto = folderbox.get(foldersel[0])
todo = []
for i in sel:
line = scanbox.get(i)
if scanparser.match(line) >= 0:
todo.append(string.atoi(scanparser.group(1)))
print 'refile', todo, tofolder
if lastrefile != refileto or not tofolder:
print 'new folder'
lastrefile = refileto
tofolder = None
tofolder = mh.openfolder(lastrefile)
mhf.refilemessages(todo, tofolder)
rescan()
fixfocus(min(todo), itop)
def fixfocus(near, itop):
n = scanbox.size()
for i in range(n):
line = scanbox.get(`i`)
if scanparser.match(line) >= 0:
num = string.atoi(scanparser.group(1))
if num >= near:
break
else:
i = 'end'
scanbox.select_from(i)
print 'yview', `itop`
scanbox.yview(itop)
def setfolders():
folderbox.delete(0, 'end')
for fn in mh.listallfolders():
folderbox.insert('end', fn)
def rescan():
global viewer
if viewer:
viewer.destroy()
viewer = None
scanbox.delete(0, 'end')
for line in scanfolder(folder, seq):
scanbox.insert('end', line)
def scanfolder(folder = 'inbox', sequence = 'all'):
return map(
lambda line: line[:-1],
os.popen('scan +%s %s' % (folder, sequence), 'r').readlines())
main()
#! /ufs/guido/bin/sgi/tkpython
# A Python program implementing rmt, an application for remotely
# controlling other Tk applications.
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
# Note that because of forward references in the original, we
# sometimes delay bindings until after the corresponding procedure is
# defined. We also introduce names for some unnamed code blocks in
# the original because of restrictions on lambda forms in Python.
from Tkinter import *
# 1. Create basic application structure: menu bar on top of
# text widget, scrollbar on right.
root = Tk()
tk = root.tk
mBar = Frame(root, {'relief': 'raised', 'bd': 2,
Pack: {'side': 'top', 'fill': 'x'}})
f = Frame(root)
f.pack({'expand': 1, 'fill': 'both'})
s = Scrollbar(f, {'relief': 'flat',
Pack: {'side': 'right', 'fill': 'y'}})
t = Text(f, {'relief': 'raised', 'bd': 2, 'yscrollcommand': (s, 'set'),
'setgrid': 1,
Pack: {'side': 'left', 'fill': 'both', 'expand': 1}})
t.tag_config('bold', {'font': '-Adobe-Courier-Bold-R-Normal-*-120-*'})
s['command'] = (t, 'yview')
root.title('Tk Remote Controller')
root.iconname('Tk Remote')
# 2. Create menu button and menus.
file = Menubutton(mBar, {'text': 'File', 'underline': 0,
Pack: {'side': 'left'}})
file_m = Menu(file)
file['menu'] = file_m
file_m_apps = Menu(file_m)
file_m.add('cascade', {'label': 'Select Application', 'underline': 0,
'menu': file_m_apps})
file_m.add('command', {'label': 'Quit', 'underline': 0, 'command': 'exit'})
# 3. Create bindings for text widget to allow commands to be
# entered and information to be selected. New characters
# can only be added at the end of the text (can't ever move
# insertion point).
def single1(e):
x = e.x
y = e.y
tk.setvar('tk_priv(selectMode)', 'char')
t.mark_set('anchor', At(x, y))
# Should focus W
t.bind('<1>', single1)
def double1(e):
x = e.x
y = e.y
tk.setvar('tk_priv(selectMode)', 'word')
tk.call('tk_textSelectTo', t, At(x, y))
t.bind('<Double-1>', double1)
def triple1(e):
x = e.x
y = e.y
tk.setvar('tk_priv(selectMode)', 'line')
tk.call('tk_textSelectTo', t, At(x, y))
t.bind('<Triple-1>', triple1)
def returnkey(e):
t.insert('insert', '\n')
invoke()
t.bind('<Return>', returnkey)
def controlv(e):
t.insert('insert', tk.call('selection', 'get'))
t.yview_pickplace('insert')
if t.index('insert')[-2:] == '.0':
invoke()
t.bind('<Control-v>', controlv)
# 4. Procedure to backspace over one character, as long as
# the character isn't part of the prompt.
def backspace(e):
if t.index('promptEnd') != t.index('insert - 1 char'):
t.delete('insert - 1 char', 'insert')
t.yview_pickplace('insert')
t.bind('<BackSpace>', backspace)
t.bind('<Control-h>', backspace)
t.bind('<Delete>', backspace)
# 5. Procedure that's invoked when return is typed: if
# there's not yet a complete command (e.g. braces are open)
# then do nothing. Otherwise, execute command (locally or
# remotely), output the result or error message, and issue
# a new prompt.
def invoke():
cmd = t.get('promptEnd + 1 char', 'insert')
if tk.getboolean(tk.call('info', 'complete', cmd)):
if app == tk.call('winfo', 'name', '.'):
msg = tk.call('eval', cmd)
else:
msg = tk.call('send', app, cmd)
if msg:
t.insert('insert', msg + '\n')
prompt()
t.yview_pickplace('insert')
def prompt():
t.insert('insert', app + ': ')
t.mark_set('promptEnd', 'insert - 1 char')
t.tag_add('bold', 'insert linestart', 'promptEnd')
# 6. Procedure to select a new application. Also changes
# the prompt on the current command line to reflect the new
# name.
def newApp(appName):
global app
app = appName
t.delete('promptEnd linestart', 'promptEnd')
t.insert('promptEnd', appName + ':')
t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
newApp_tcl = `id(newApp)`
tk.createcommand(newApp_tcl, newApp)
def fillAppsMenu():
file_m_apps.add('command')
file_m_apps.delete(0, 'last')
names = tk.splitlist(tk.call('winfo', 'interps'))
names = map(None, names) # convert tuple to list
names.sort()
for name in names:
file_m_apps.add('command', {'label': name,
'command': (newApp_tcl, name)})
file_m_apps['postcommand'] = fillAppsMenu
mBar.tk_menuBar(file)
# 7. Miscellaneous initialization.
app = tk.call('winfo', 'name', '.')
prompt()
tk.call('focus', t)
root.mainloop()
# tst.py
from Tkinter import *
import sys
def do_hello():
print 'Hello world!'
class Quit(Button):
def action(self):
self.quit()
def __init__(self, master=None, cnf={}):
Button.__init__(self, master,
{'text': 'Quit',
'command': self.action})
Button.config(self, cnf)
class Stuff(Canvas):
def enter(self, e):
print 'Enter'
self.itemconfig('current', {'fill': 'red'})
def leave(self, e):
print 'Leave'
self.itemconfig('current', {'fill': 'blue'})
def __init__(self, master=None, cnf={}):
Canvas.__init__(self, master,
{'width': 100, 'height': 100})
Canvas.config(self, cnf)
self.create_rectangle(30, 30, 70, 70,
{'fill': 'red', 'tags': 'box'})
Canvas.bind(self, 'box', '<Enter>', self.enter)
Canvas.bind(self, 'box', '<Leave>', self.leave)
class Test(Frame):
text = 'Testing'
num = 1
def do_xy(self, e):
print (e.x, e.y)
def do_test(self):
if not self.num % 10:
self.text = 'Testing 1 ...'
self.text = self.text + ' ' + `self.num`
self.num = self.num + 1
self.testing['text'] = self.text
def do_err(self):
1/0
def do_after(self):
self.testing.invoke()
self.after(10000, self.do_after)
def __init__(self, master=None):
Frame.__init__(self, master)
self['bd'] = 30
Pack.config(self)
self.bind('<Motion>', self.do_xy)
self.hello = Button(self, {'name': 'hello',
'text': 'Hello',
'command': do_hello,
Pack: {'fill': 'both'}})
self.testing = Button(self)
self.testing['text'] = self.text
self.testing['command'] = self.do_test
Pack.config(self.testing, {'fill': 'both'})
self.err = Button(self, {'text': 'Error',
'command': self.do_err,
Pack: {'fill': 'both'}})
self.quit = Quit(self, {Pack: {'fill': 'both'}})
self.exit = Button(self,
{'text': 'Exit',
'command': lambda: sys.exit(0),
Pack: {'fill': 'both'}})
self.stuff = Stuff(self, {Pack: {'padx': 2, 'pady': 2}})
self.do_after()
test = Test()
test.master.title('Tkinter Test')
test.master.iconname('Test')
test.master.maxsize(500, 500)
test.testing.invoke()
# Use the -i option and type ^C to get a prompt
test.mainloop()
# This is about all it requires to write a wish shell in Python!
import tkinter
tk = tkinter.create(':0', 'wish', 'Tk', 1)
tk.call('update')
cmd = ''
while 1:
if cmd: prompt = ''
else: prompt = '% '
try:
line = raw_input(prompt)
except EOFError:
break
cmd = cmd + (line + '\n')
tk.record(line)
if tk.getboolean(tk.call('info', 'complete', cmd)):
try:
result = tk.call('eval', cmd)
except tkinter.TclError, msg:
print 'TclError:', msg
else:
if result: print result
cmd = ''
# This module exports classes for the various canvas item types
# vi:set tabsize=4:
from Tkinter import Canvas, _isfunctype
class CanvasItem:
def __init__(self, canvas, itemType, args = (), cnf={}):
self.canvas = canvas
self.id = canvas._create(itemType, args + (cnf,))
def __str__(self):
return str(self.id)
def __repr__(self):
return '<%s, id=%d>' % (self.__class__.__name__, self.id)
def __del__(self):
self.canvas.delete(self.id)
delete = __del__
def __getitem__(self, key):
v = self.canvas.tk.split(self.canvas.tk.call(self.canvas.pathName,
'itemconfigure',
str(self.id),
'-' + key))
return v[4]
def __setitem__(self, key, value):
self.canvas._itemconfig(self.id, {key: value})
def keys(self):
if not hasattr(self, '_keys'):
self._keys = map(lambda x, tk=self.canvas.tk:
tk.splitlist(x)[0][1:],
self.canvas._splitlist(
self.canvas.cmd('itemconfigure', self.id)))
return self._keys
def has_key(self, key):
return key in self.keys()
def addtag(self, tag, option='withtag'):
self.canvas.addtag(tag, option, self.id)
def bbox(self):
x1, y1, x2, y2 = self.canvas.bbox(self.id)
return (x1, y1), (x2, y2)
def bind(self, sequence=None, command=None):
return self.canvas.bind(self.id, sequence, command)
def coords(self, pts = ()):
flat = ()
for x, y in pts: flat = flat + (x, y)
return apply(self.canvas.coords, (self.id,) + flat)
def dchars(self, first, last=None):
self.canvas.dchars(self.id, first, last)
def dtag(self, ttd):
self.canvas.dtag(self.id, ttd)
def focus(self):
self.canvas.focus(self.id)
def gettags(self):
return self.canvas.gettags(self.id)
def icursor(self):
self.canvas.icursor(self.id)
def index(self):
return self.canvas.index(self.id)
def insert(self, beforethis, string):
self.canvas.insert(self.id, beforethis, string)
def lower(self, belowthis=None):
self.canvas.lower(self.id, belowthis)
def move(self, xamount, yamount):
self.canvas.move(self.id, xamount, yamount)
def raise_(self, abovethis=None):
self.canvas.raise_(self.id, abovethis)
def scale(self, xorigin, yorigin, xscale, yscale):
self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
def type(self):
return self.canvas.type(self.id)
class Arc(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'arc',
(str(x1), str(y1), str(x2), str(y2)), cnf)
class Bitmap(CanvasItem):
def __init__(self, canvas, (x1, y1), cnf={}):
CanvasItem.__init__(self, canvas, 'bitmap', (str(x1), str(y1)), cnf)
class Line(CanvasItem):
def __init__(self, canvas, pts, cnf={}):
pts = reduce(lambda a, b: a+b,
map(lambda pt: (str(pt[0]), str(pt[1])), pts))
CanvasItem.__init__(self, canvas, 'line', pts, cnf)
class Oval(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'oval',
(str(x1), str(y1), str(x2), str(y2)), cnf)
class Polygon(CanvasItem):
def __init__(self, canvas, pts, cnf={}):
pts = reduce(lambda a, b: a+b,
map(lambda pt: (str(pt[0]), str(pt[1])), pts))
CanvasItem.__init__(self, canvas, 'polygon', pts, cnf)
class Curve(Polygon):
def __init__(self, canvas, pts, cnf={}):
cnf['smooth'] = 'yes'
Polygon.__init__(self, canvas, pts, cnf)
class Rectangle(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'rectangle',
(str(x1), str(y1), str(x2), str(y2)), cnf)
# XXX Can't use name "Text" since that is already taken by the Text widget...
class String(CanvasItem):
def __init__(self, canvas, (x1, y1), cnf={}):
CanvasItem.__init__(self, canvas, 'text', (str(x1), str(y1)), cnf)
class Window(CanvasItem):
def __init__(self, canvas, where, cnf={}):
CanvasItem.__init__(self, canvas, 'window',
(str(where[0]), str(where[1])), cnf)
# A ScrolledText widget feels like a text widget but also has a
# vertical scroll bar on its right. (Later, options may be added to
# add a horizontal bar as well, to make the bars disappear
# automatically when not needed, to move them to the other side of the
# window, etc.)
#
# Configuration options are passed to the Text widget.
# A Frame widget is inserted between the master and the text, to hold
# the Scrollbar widget.
# Most methods calls are passed to the Text widget; the pack command
# is redirected to the Frame widget however.
from Tkinter import *
class ScrolledText(Pack, Place):
def __init__(self, master=None, cnf={}):
fcnf = {}
self.frame = Frame(master, {})
if cnf.has_key(Pack):
self.frame.pack(cnf[Pack])
del cnf[Pack]
self.vbar = Scrollbar(self.frame, {})
self.vbar.pack({'side': 'right', 'fill': 'y'})
cnf[Pack] = {'side': 'left', 'fill': 'both',
'expand': 'yes'}
self.text = Text(self.frame, cnf)
self.text['yscrollcommand'] = (self.vbar, 'set')
self.vbar['command'] = (self.text, 'yview')
self.insert = self.text.insert
# XXX should do all Text methods...
self.pack = self.frame.pack
self.forget = self.frame.forget
self.tk = master.tk
def __str__(self):
return str(self.frame)
This diff is collapsed.
# This module exports classes for the various canvas item types
# vi:set tabsize=4:
from Tkinter import Canvas, _isfunctype
class CanvasItem:
def __init__(self, canvas, itemType, args = (), cnf={}):
self.canvas = canvas
self.id = canvas._create(itemType, args + (cnf,))
def __str__(self):
return str(self.id)
def __repr__(self):
return '<%s, id=%d>' % (self.__class__.__name__, self.id)
def __del__(self):
self.canvas.delete(self.id)
delete = __del__
def __getitem__(self, key):
v = self.canvas.tk.split(self.canvas.tk.call(self.canvas.pathName,
'itemconfigure',
str(self.id),
'-' + key))
return v[4]
def __setitem__(self, key, value):
self.canvas._itemconfig(self.id, {key: value})
def keys(self):
if not hasattr(self, '_keys'):
self._keys = map(lambda x, tk=self.canvas.tk:
tk.splitlist(x)[0][1:],
self.canvas._splitlist(
self.canvas.cmd('itemconfigure', self.id)))
return self._keys
def has_key(self, key):
return key in self.keys()
def addtag(self, tag, option='withtag'):
self.canvas.addtag(tag, option, self.id)
def bbox(self):
x1, y1, x2, y2 = self.canvas.bbox(self.id)
return (x1, y1), (x2, y2)
def bind(self, sequence=None, command=None):
return self.canvas.bind(self.id, sequence, command)
def coords(self, pts = ()):
flat = ()
for x, y in pts: flat = flat + (x, y)
return apply(self.canvas.coords, (self.id,) + flat)
def dchars(self, first, last=None):
self.canvas.dchars(self.id, first, last)
def dtag(self, ttd):
self.canvas.dtag(self.id, ttd)
def focus(self):
self.canvas.focus(self.id)
def gettags(self):
return self.canvas.gettags(self.id)
def icursor(self):
self.canvas.icursor(self.id)
def index(self):
return self.canvas.index(self.id)
def insert(self, beforethis, string):
self.canvas.insert(self.id, beforethis, string)
def lower(self, belowthis=None):
self.canvas.lower(self.id, belowthis)
def move(self, xamount, yamount):
self.canvas.move(self.id, xamount, yamount)
def raise_(self, abovethis=None):
self.canvas.raise_(self.id, abovethis)
def scale(self, xorigin, yorigin, xscale, yscale):
self.canvas.scale(self.id, xorigin, yorigin, xscale, yscale)
def type(self):
return self.canvas.type(self.id)
class Arc(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'arc',
(str(x1), str(y1), str(x2), str(y2)), cnf)
class Bitmap(CanvasItem):
def __init__(self, canvas, (x1, y1), cnf={}):
CanvasItem.__init__(self, canvas, 'bitmap', (str(x1), str(y1)), cnf)
class Line(CanvasItem):
def __init__(self, canvas, pts, cnf={}):
pts = reduce(lambda a, b: a+b,
map(lambda pt: (str(pt[0]), str(pt[1])), pts))
CanvasItem.__init__(self, canvas, 'line', pts, cnf)
class Oval(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'oval',
(str(x1), str(y1), str(x2), str(y2)), cnf)
class Polygon(CanvasItem):
def __init__(self, canvas, pts, cnf={}):
pts = reduce(lambda a, b: a+b,
map(lambda pt: (str(pt[0]), str(pt[1])), pts))
CanvasItem.__init__(self, canvas, 'polygon', pts, cnf)
class Curve(Polygon):
def __init__(self, canvas, pts, cnf={}):
cnf['smooth'] = 'yes'
Polygon.__init__(self, canvas, pts, cnf)
class Rectangle(CanvasItem):
def __init__(self, canvas, (x1, y1), (x2, y2), cnf={}):
CanvasItem.__init__(self, canvas, 'rectangle',
(str(x1), str(y1), str(x2), str(y2)), cnf)
# XXX Can't use name "Text" since that is already taken by the Text widget...
class String(CanvasItem):
def __init__(self, canvas, (x1, y1), cnf={}):
CanvasItem.__init__(self, canvas, 'text', (str(x1), str(y1)), cnf)
class Window(CanvasItem):
def __init__(self, canvas, where, cnf={}):
CanvasItem.__init__(self, canvas, 'window',
(str(where[0]), str(where[1])), cnf)
# A ScrolledText widget feels like a text widget but also has a
# vertical scroll bar on its right. (Later, options may be added to
# add a horizontal bar as well, to make the bars disappear
# automatically when not needed, to move them to the other side of the
# window, etc.)
#
# Configuration options are passed to the Text widget.
# A Frame widget is inserted between the master and the text, to hold
# the Scrollbar widget.
# Most methods calls are passed to the Text widget; the pack command
# is redirected to the Frame widget however.
from Tkinter import *
class ScrolledText(Pack, Place):
def __init__(self, master=None, cnf={}):
fcnf = {}
self.frame = Frame(master, {})
if cnf.has_key(Pack):
self.frame.pack(cnf[Pack])
del cnf[Pack]
self.vbar = Scrollbar(self.frame, {})
self.vbar.pack({'side': 'right', 'fill': 'y'})
cnf[Pack] = {'side': 'left', 'fill': 'both',
'expand': 'yes'}
self.text = Text(self.frame, cnf)
self.text['yscrollcommand'] = (self.vbar, 'set')
self.vbar['command'] = (self.text, 'yview')
self.insert = self.text.insert
# XXX should do all Text methods...
self.pack = self.frame.pack
self.forget = self.frame.forget
self.tk = master.tk
def __str__(self):
return str(self.frame)
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment