PageRenderTime 531ms CodeModel.GetById 95ms app.highlight 127ms RepoModel.GetById 179ms app.codeStats 0ms

/Demo/tkinter/guido/rmt.py

http://unladen-swallow.googlecode.com/
Python | 159 lines | 101 code | 29 blank | 29 comment | 7 complexity | 1f6d300909b102b969b8cb22563fd3b2 MD5 | raw file
  1#! /usr/bin/env python
  2
  3# A Python program implementing rmt, an application for remotely
  4# controlling other Tk applications.
  5# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.5-8, pp. 273-276.
  6
  7# Note that because of forward references in the original, we
  8# sometimes delay bindings until after the corresponding procedure is
  9# defined.  We also introduce names for some unnamed code blocks in
 10# the original because of restrictions on lambda forms in Python.
 11
 12# XXX This should be written in a more Python-like style!!!
 13
 14from Tkinter import *
 15import sys
 16
 17# 1. Create basic application structure: menu bar on top of
 18# text widget, scrollbar on right.
 19
 20root = Tk()
 21tk = root.tk
 22mBar = Frame(root, relief=RAISED, borderwidth=2)
 23mBar.pack(fill=X)
 24
 25f = Frame(root)
 26f.pack(expand=1, fill=BOTH)
 27s = Scrollbar(f, relief=FLAT)
 28s.pack(side=RIGHT, fill=Y)
 29t = Text(f, relief=RAISED, borderwidth=2, yscrollcommand=s.set, setgrid=1)
 30t.pack(side=LEFT, fill=BOTH, expand=1)
 31t.tag_config('bold', font='-Adobe-Courier-Bold-R-Normal-*-120-*')
 32s['command'] = t.yview
 33
 34root.title('Tk Remote Controller')
 35root.iconname('Tk Remote')
 36
 37# 2. Create menu button and menus.
 38
 39file = Menubutton(mBar, text='File', underline=0)
 40file.pack(side=LEFT)
 41file_m = Menu(file)
 42file['menu'] = file_m
 43file_m_apps = Menu(file_m, tearoff=0)
 44file_m.add_cascade(label='Select Application', underline=0,
 45                   menu=file_m_apps)
 46file_m.add_command(label='Quit', underline=0, command=sys.exit)
 47
 48# 3. Create bindings for text widget to allow commands to be
 49# entered and information to be selected.  New characters
 50# can only be added at the end of the text (can't ever move
 51# insertion point).
 52
 53def single1(e):
 54    x = e.x
 55    y = e.y
 56    t.setvar('tk_priv(selectMode)', 'char')
 57    t.mark_set('anchor', At(x, y))
 58    # Should focus W
 59t.bind('<1>', single1)
 60
 61def double1(e):
 62    x = e.x
 63    y = e.y
 64    t.setvar('tk_priv(selectMode)', 'word')
 65    t.tk_textSelectTo(At(x, y))
 66t.bind('<Double-1>', double1)
 67
 68def triple1(e):
 69    x = e.x
 70    y = e.y
 71    t.setvar('tk_priv(selectMode)', 'line')
 72    t.tk_textSelectTo(At(x, y))
 73t.bind('<Triple-1>', triple1)
 74
 75def returnkey(e):
 76    t.insert(AtInsert(), '\n')
 77    invoke()
 78t.bind('<Return>', returnkey)
 79
 80def controlv(e):
 81    t.insert(AtInsert(), t.selection_get())
 82    t.yview_pickplace(AtInsert())
 83    if t.index(AtInsert())[-2:] == '.0':
 84        invoke()
 85t.bind('<Control-v>', controlv)
 86
 87# 4. Procedure to backspace over one character, as long as
 88# the character isn't part of the prompt.
 89
 90def backspace(e):
 91    if t.index('promptEnd') != t.index('insert - 1 char'):
 92        t.delete('insert - 1 char', AtInsert())
 93        t.yview_pickplace(AtInsert())
 94t.bind('<BackSpace>', backspace)
 95t.bind('<Control-h>', backspace)
 96t.bind('<Delete>', backspace)
 97
 98
 99# 5. Procedure that's invoked when return is typed:  if
100# there's not yet a complete command (e.g. braces are open)
101# then do nothing.  Otherwise, execute command (locally or
102# remotely), output the result or error message, and issue
103# a new prompt.
104
105def invoke():
106    cmd = t.get('promptEnd + 1 char', AtInsert())
107    if t.getboolean(tk.call('info', 'complete', cmd)): # XXX
108        if app == root.winfo_name():
109            msg = tk.call('eval', cmd) # XXX
110        else:
111            msg = t.send(app, cmd)
112        if msg:
113            t.insert(AtInsert(), msg + '\n')
114        prompt()
115    t.yview_pickplace(AtInsert())
116
117def prompt():
118    t.insert(AtInsert(), app + ': ')
119    t.mark_set('promptEnd', 'insert - 1 char')
120    t.tag_add('bold', 'insert linestart', 'promptEnd')
121
122# 6. Procedure to select a new application.  Also changes
123# the prompt on the current command line to reflect the new
124# name.
125
126def newApp(appName):
127    global app
128    app = appName
129    t.delete('promptEnd linestart', 'promptEnd')
130    t.insert('promptEnd', appName + ':')
131    t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
132
133def fillAppsMenu():
134    file_m_apps.add('command')
135    file_m_apps.delete(0, 'last')
136    names = root.winfo_interps()
137    names = list(names)
138    names.sort()
139    for name in names:
140        try:
141            root.send(name, 'winfo name .')
142        except TclError:
143            # Inoperative window -- ignore it
144            pass
145        else:
146            file_m_apps.add_command(
147                label=name,
148                command=lambda name=name: newApp(name))
149
150file_m_apps['postcommand'] = fillAppsMenu
151mBar.tk_menuBar(file)
152
153# 7. Miscellaneous initialization.
154
155app = root.winfo_name()
156prompt()
157t.focus()
158
159root.mainloop()