cpython/Demo/tkinter/guido/rmt.py
Georg Brandl f55aa80b37 Merged revisions 85820,85823,85825,85840,85843-85845,85849-85851,85855,85867,85875,85907-85908,85911,85914 via svnmerge from
svn+ssh://svn.python.org/python/branches/py3k

........
  r85820 | georg.brandl | 2010-10-24 16:20:22 +0200 (So, 24 Okt 2010) | 1 line

  Remove usage of exception indexing.
........
  r85823 | georg.brandl | 2010-10-24 16:32:45 +0200 (So, 24 Okt 2010) | 1 line

  Fix style.
........
  r85825 | georg.brandl | 2010-10-24 17:16:02 +0200 (So, 24 Okt 2010) | 1 line

  Add documentation about the default warnings filters.
........
  r85840 | georg.brandl | 2010-10-25 19:50:20 +0200 (Mo, 25 Okt 2010) | 1 line

  #3018: tkinter demo fixes for py3k.
........
  r85843 | georg.brandl | 2010-10-26 08:59:23 +0200 (Di, 26 Okt 2010) | 1 line

  Markup fix.
........
  r85844 | georg.brandl | 2010-10-26 12:39:14 +0200 (Di, 26 Okt 2010) | 1 line

  Work a bit more on tkinter demos.
........
  r85845 | georg.brandl | 2010-10-26 12:42:16 +0200 (Di, 26 Okt 2010) | 1 line

  faqwiz is removed.
........
  r85849 | georg.brandl | 2010-10-26 21:31:06 +0200 (Di, 26 Okt 2010) | 1 line

  #10200: typo.
........
  r85850 | georg.brandl | 2010-10-26 21:58:11 +0200 (Di, 26 Okt 2010) | 1 line

  #10200: typo.
........
  r85851 | georg.brandl | 2010-10-26 22:12:37 +0200 (Di, 26 Okt 2010) | 1 line

  Fix import.
........
  r85855 | georg.brandl | 2010-10-27 09:21:54 +0200 (Mi, 27 Okt 2010) | 1 line

  Encoding fix.
........
  r85867 | georg.brandl | 2010-10-27 22:01:51 +0200 (Mi, 27 Okt 2010) | 1 line

  Add David.
........
  r85875 | georg.brandl | 2010-10-28 10:38:30 +0200 (Do, 28 Okt 2010) | 1 line

  Fix bytes/str issues in get-remote-certificate.py.
........
  r85907 | georg.brandl | 2010-10-29 06:54:13 +0200 (Fr, 29 Okt 2010) | 1 line

  #10222: fix for overzealous AIX compiler.
........
  r85908 | georg.brandl | 2010-10-29 07:22:17 +0200 (Fr, 29 Okt 2010) | 1 line

  send_bytes obviously needs bytes...
........
  r85911 | georg.brandl | 2010-10-29 07:36:28 +0200 (Fr, 29 Okt 2010) | 1 line

  Fix markup error and update false positive entries from "make suspicious".
........
  r85914 | georg.brandl | 2010-10-29 08:17:38 +0200 (Fr, 29 Okt 2010) | 1 line

  (?:...) is a non-capturing, but still grouping construct.
........
2010-11-26 08:59:40 +00:00

159 lines
4.4 KiB
Python
Executable file

#! /usr/bin/env python
# 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.
# XXX This should be written in a more Python-like style!!!
from tkinter import *
import sys
# 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, borderwidth=2)
mBar.pack(fill=X)
f = Frame(root)
f.pack(expand=1, fill=BOTH)
s = Scrollbar(f, relief=FLAT)
s.pack(side=RIGHT, fill=Y)
t = Text(f, relief=RAISED, borderwidth=2, yscrollcommand=s.set, setgrid=1)
t.pack(side=LEFT, fill=BOTH, expand=1)
t.tag_config('bold')
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)
file.pack(side=LEFT)
file_m = Menu(file)
file['menu'] = file_m
file_m_apps = Menu(file_m, tearoff=0)
file_m.add_cascade(label='Select Application', underline=0,
menu=file_m_apps)
file_m.add_command(label='Quit', underline=0, command=sys.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
t.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
t.setvar('tk_priv(selectMode)', 'word')
t.tk_textSelectTo(At(x, y))
t.bind('<Double-1>', double1)
def triple1(e):
x = e.x
y = e.y
t.setvar('tk_priv(selectMode)', 'line')
t.tk_textSelectTo(At(x, y))
t.bind('<Triple-1>', triple1)
def returnkey(e):
t.insert(AtInsert(), '\n')
invoke()
t.bind('<Return>', returnkey)
def controlv(e):
t.insert(AtInsert(), t.selection_get())
t.yview_pickplace(AtInsert())
if t.index(AtInsert())[-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', AtInsert())
t.yview_pickplace(AtInsert())
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', AtInsert())
if t.getboolean(tk.call('info', 'complete', cmd)): # XXX
if app == root.winfo_name():
msg = tk.call('eval', cmd) # XXX
else:
msg = t.send(app, cmd)
if msg:
t.insert(AtInsert(), msg + '\n')
prompt()
t.yview_pickplace(AtInsert())
def prompt():
t.insert(AtInsert(), 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')
def fillAppsMenu():
file_m_apps.add('command')
file_m_apps.delete(0, 'last')
names = root.winfo_interps()
names = list(names) # convert tuple to list
names.sort()
for name in names:
try:
root.send(name, 'winfo name .')
except TclError:
# Inoperative window -- ignore it
pass
else:
file_m_apps.add_command(
label=name,
command=lambda name=name: newApp(name))
file_m_apps['postcommand'] = fillAppsMenu
mBar.tk_menuBar(file)
# 7. Miscellaneous initialization.
app = root.winfo_name()
prompt()
t.focus()
root.mainloop()