blob: 44bbcf4fc73f52c611bebdde3f511a6b2d505f94 [file] [log] [blame]
Guido van Rossum18468821994-06-20 07:49:28 +00001#! /ufs/guido/bin/sgi/tkpython
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
Guido van Rossum74f25651994-07-13 13:08:01 +000012# XXX This should be written in a more Python-like style!!!
13
Guido van Rossum18468821994-06-20 07:49:28 +000014from Tkinter import *
15
16# 1. Create basic application structure: menu bar on top of
17# text widget, scrollbar on right.
18
19root = Tk()
20tk = root.tk
21mBar = Frame(root, {'relief': 'raised', 'bd': 2,
22 Pack: {'side': 'top', 'fill': 'x'}})
23f = Frame(root)
24f.pack({'expand': 1, 'fill': 'both'})
25s = Scrollbar(f, {'relief': 'flat',
26 Pack: {'side': 'right', 'fill': 'y'}})
27t = Text(f, {'relief': 'raised', 'bd': 2, 'yscrollcommand': (s, 'set'),
28 'setgrid': 1,
29 Pack: {'side': 'left', 'fill': 'both', 'expand': 1}})
30
31t.tag_config('bold', {'font': '-Adobe-Courier-Bold-R-Normal-*-120-*'})
32s['command'] = (t, 'yview')
33root.title('Tk Remote Controller')
34root.iconname('Tk Remote')
35
36# 2. Create menu button and menus.
37
38file = Menubutton(mBar, {'text': 'File', 'underline': 0,
39 Pack: {'side': 'left'}})
40file_m = Menu(file)
41file['menu'] = file_m
42file_m_apps = Menu(file_m)
43file_m.add('cascade', {'label': 'Select Application', 'underline': 0,
44 'menu': file_m_apps})
45file_m.add('command', {'label': 'Quit', 'underline': 0, 'command': 'exit'})
46
47# 3. Create bindings for text widget to allow commands to be
48# entered and information to be selected. New characters
49# can only be added at the end of the text (can't ever move
50# insertion point).
51
52def single1(e):
53 x = e.x
54 y = e.y
Guido van Rossumdf096911994-06-20 09:08:51 +000055 t.setvar('tk_priv(selectMode)', 'char')
Guido van Rossum18468821994-06-20 07:49:28 +000056 t.mark_set('anchor', At(x, y))
57 # Should focus W
58t.bind('<1>', single1)
59
60def double1(e):
61 x = e.x
62 y = e.y
Guido van Rossumdf096911994-06-20 09:08:51 +000063 t.setvar('tk_priv(selectMode)', 'word')
64 t.tk_textSelectTo(At(x, y))
Guido van Rossum18468821994-06-20 07:49:28 +000065t.bind('<Double-1>', double1)
66
67def triple1(e):
68 x = e.x
69 y = e.y
Guido van Rossumdf096911994-06-20 09:08:51 +000070 t.setvar('tk_priv(selectMode)', 'line')
71 t.tk_textSelectTo(At(x, y))
Guido van Rossum18468821994-06-20 07:49:28 +000072t.bind('<Triple-1>', triple1)
73
74def returnkey(e):
Guido van Rossumdf096911994-06-20 09:08:51 +000075 t.insert(AtInsert(), '\n')
Guido van Rossum18468821994-06-20 07:49:28 +000076 invoke()
77t.bind('<Return>', returnkey)
78
79def controlv(e):
Guido van Rossumdf096911994-06-20 09:08:51 +000080 t.insert(AtInsert(), t.selection_get())
81 t.yview_pickplace(AtInsert())
82 if t.index(AtInsert())[-2:] == '.0':
Guido van Rossum18468821994-06-20 07:49:28 +000083 invoke()
84t.bind('<Control-v>', controlv)
85
86# 4. Procedure to backspace over one character, as long as
87# the character isn't part of the prompt.
88
89def backspace(e):
90 if t.index('promptEnd') != t.index('insert - 1 char'):
Guido van Rossumdf096911994-06-20 09:08:51 +000091 t.delete('insert - 1 char', AtInsert())
92 t.yview_pickplace(AtInsert())
Guido van Rossum18468821994-06-20 07:49:28 +000093t.bind('<BackSpace>', backspace)
94t.bind('<Control-h>', backspace)
95t.bind('<Delete>', backspace)
96
97
98# 5. Procedure that's invoked when return is typed: if
99# there's not yet a complete command (e.g. braces are open)
100# then do nothing. Otherwise, execute command (locally or
101# remotely), output the result or error message, and issue
102# a new prompt.
103
104def invoke():
Guido van Rossumdf096911994-06-20 09:08:51 +0000105 cmd = t.get('promptEnd + 1 char', AtInsert())
106 if t.getboolean(tk.call('info', 'complete', cmd)): # XXX
107 if app == root.winfo_name():
108 msg = tk.call('eval', cmd) # XXX
Guido van Rossum18468821994-06-20 07:49:28 +0000109 else:
Guido van Rossumdf096911994-06-20 09:08:51 +0000110 msg = t.send(app, cmd)
Guido van Rossum18468821994-06-20 07:49:28 +0000111 if msg:
Guido van Rossumdf096911994-06-20 09:08:51 +0000112 t.insert(AtInsert(), msg + '\n')
Guido van Rossum18468821994-06-20 07:49:28 +0000113 prompt()
Guido van Rossumdf096911994-06-20 09:08:51 +0000114 t.yview_pickplace(AtInsert())
Guido van Rossum18468821994-06-20 07:49:28 +0000115
116def prompt():
Guido van Rossumdf096911994-06-20 09:08:51 +0000117 t.insert(AtInsert(), app + ': ')
Guido van Rossum18468821994-06-20 07:49:28 +0000118 t.mark_set('promptEnd', 'insert - 1 char')
119 t.tag_add('bold', 'insert linestart', 'promptEnd')
120
121# 6. Procedure to select a new application. Also changes
122# the prompt on the current command line to reflect the new
123# name.
124
125def newApp(appName):
126 global app
127 app = appName
128 t.delete('promptEnd linestart', 'promptEnd')
129 t.insert('promptEnd', appName + ':')
130 t.tag_add('bold', 'promptEnd linestart', 'promptEnd')
131
Guido van Rossum18468821994-06-20 07:49:28 +0000132def fillAppsMenu():
133 file_m_apps.add('command')
134 file_m_apps.delete(0, 'last')
Guido van Rossumdf096911994-06-20 09:08:51 +0000135 names = root.winfo_interps()
Guido van Rossum18468821994-06-20 07:49:28 +0000136 names = map(None, names) # convert tuple to list
137 names.sort()
138 for name in names:
Guido van Rossumdf096911994-06-20 09:08:51 +0000139 try:
140 root.send(name, 'winfo name .')
141 except TclError:
142 # Inoperative window -- ignore it
143 pass
144 else:
145 file_m_apps.add('command', {'label': name,
146 'command':
147 lambda name=name:
148 newApp(name)})
Guido van Rossum18468821994-06-20 07:49:28 +0000149
150file_m_apps['postcommand'] = fillAppsMenu
151mBar.tk_menuBar(file)
152
153# 7. Miscellaneous initialization.
154
Guido van Rossumdf096911994-06-20 09:08:51 +0000155app = root.winfo_name()
Guido van Rossum18468821994-06-20 07:49:28 +0000156prompt()
Guido van Rossumdf096911994-06-20 09:08:51 +0000157t.focus()
Guido van Rossum18468821994-06-20 07:49:28 +0000158
159root.mainloop()