home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / tkinter / guido / rmt.py < prev    next >
Text File  |  1996-11-27  |  4KB  |  160 lines

  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.  
  14. from Tkinter import *
  15. import sys
  16.  
  17. # 1. Create basic application structure: menu bar on top of
  18. # text widget, scrollbar on right.
  19.  
  20. root = Tk()
  21. tk = root.tk
  22. mBar = Frame(root, relief=RAISED, borderwidth=2)
  23. mBar.pack(fill=X)
  24.  
  25. f = Frame(root)
  26. f.pack(expand=1, fill=BOTH)
  27. s = Scrollbar(f, relief=FLAT)
  28. s.pack(side=RIGHT, fill=Y)
  29. t = Text(f, relief=RAISED, borderwidth=2, yscrollcommand=s.set, setgrid=1)
  30. t.pack(side=LEFT, fill=BOTH, expand=1)
  31. t.tag_config('bold', font='-Adobe-Courier-Bold-R-Normal-*-120-*') 
  32. s['command'] = t.yview
  33.  
  34. root.title('Tk Remote Controller')
  35. root.iconname('Tk Remote')
  36.  
  37. # 2. Create menu button and menus.
  38.  
  39. file = Menubutton(mBar, text='File', underline=0)
  40. file.pack(side=LEFT)
  41. file_m = Menu(file)
  42. file['menu'] = file_m
  43. file_m_apps = Menu(file_m, tearoff=0)
  44. file_m.add_cascade(label='Select Application', underline=0,
  45.            menu=file_m_apps)
  46. file_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.  
  53. def 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
  59. t.bind('<1>', single1)
  60.  
  61. def double1(e):
  62.     x = e.x
  63.     y = e.y
  64.     t.setvar('tk_priv(selectMode)', 'word')
  65.     t.tk_textSelectTo(At(x, y))
  66. t.bind('<Double-1>', double1)
  67.  
  68. def triple1(e):
  69.     x = e.x
  70.     y = e.y
  71.     t.setvar('tk_priv(selectMode)', 'line')
  72.     t.tk_textSelectTo(At(x, y))
  73. t.bind('<Triple-1>', triple1)
  74.  
  75. def returnkey(e):
  76.     t.insert(AtInsert(), '\n')
  77.     invoke()
  78. t.bind('<Return>', returnkey)
  79.  
  80. def controlv(e):
  81.     t.insert(AtInsert(), t.selection_get())
  82.     t.yview_pickplace(AtInsert())
  83.     if t.index(AtInsert())[-2:] == '.0':
  84.         invoke()
  85. t.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.  
  90. def backspace(e):
  91.     if t.index('promptEnd') != t.index('insert - 1 char'):
  92.         t.delete('insert - 1 char', AtInsert())
  93.         t.yview_pickplace(AtInsert())
  94. t.bind('<BackSpace>', backspace)
  95. t.bind('<Control-h>', backspace)
  96. t.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.  
  105. def 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.  
  117. def 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.  
  126. def 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.  
  133. def fillAppsMenu():
  134.     file_m_apps.add('command')
  135.     file_m_apps.delete(0, 'last')
  136.     names = root.winfo_interps()
  137.     names = map(None, names) # convert tuple to list
  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.  
  150. file_m_apps['postcommand'] = fillAppsMenu
  151. mBar.tk_menuBar(file)
  152.  
  153. # 7. Miscellaneous initialization.
  154.  
  155. app = root.winfo_name()
  156. prompt()
  157. t.focus()
  158.  
  159. root.mainloop()
  160.