home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Lib / stdwin / mainloop.py < prev    next >
Text File  |  1993-12-17  |  6KB  |  257 lines

  1. # Standard main loop for *all* STDWIN applications.
  2. # This requires that applications:
  3. # - register their windows on creation and unregister them when closed
  4. # - have a 'dispatch' function as a window member
  5.  
  6.  
  7. import stdwin, stdwinq
  8. from stdwinevents import *
  9.  
  10.  
  11. # List of windows known to the main loop.
  12. #
  13. windows = []
  14.  
  15.  
  16. # Last window that ever received an event
  17. #
  18. last_window = None
  19.  
  20.  
  21. # Function to register a window.
  22. #
  23. def register(win):
  24.     # First test the dispatch function by passing it a null event --
  25.     # this catches registration of unconforming windows.
  26.     win.dispatch((WE_NULL, win, None))
  27.     if win not in windows:
  28.         windows.append(win)
  29.  
  30.  
  31. # Function to unregister a window.
  32. # It is not an error to unregister an already unregistered window
  33. # (this is useful for cleanup actions).
  34. #
  35. def unregister(win):
  36.     global last_window
  37.     if win == last_window:
  38.         last_window = None
  39.     if win in windows:
  40.         windows.remove(win) # Not in 0.9.1
  41.         # 0.9.1 solution:
  42.         #for i in range(len(windows)):
  43.         #    if windows[i] = win:
  44.         #        del windows[i]
  45.         #        break
  46.  
  47.  
  48. # Interfaces used by WindowSched.
  49. #
  50. def countwindows():
  51.     return len(windows)
  52. #
  53. def anywindow():
  54.     if windows:
  55.         return windows[0]
  56.     else:
  57.         return None
  58.  
  59.  
  60. # NEW: register any number of file descriptors
  61. #
  62. fdlist = []
  63. select_args = None
  64. select_handlers = None
  65. #
  66. def registerfd(fd, mode, handler):
  67.     if mode not in ('r', 'w', 'x'):
  68.         raise ValueError, 'mode must be r, w or x'
  69.     if type(fd) <> type(0):
  70.         fd = fd.fileno() # If this fails it's not a proper select arg
  71.     for i in range(len(fdlist)):
  72.         if fdlist[i][:2] == (fd, mode):
  73.             raise ValueError, \
  74.                 '(fd, mode) combination already registered'
  75.     fdlist.append((fd, mode, handler))
  76.     make_select_args()
  77. #
  78. def unregisterfd(fd, *args):
  79.     if type(fd) <> type(0):
  80.         fd = fd.fileno() # If this fails it's not a proper select arg
  81.     args = (fd,) + args
  82.     n = len(args)
  83.     for i in range(len(fdlist)):
  84.         if fdlist[i][:n] == args:
  85.             del fdlist[i]
  86.     make_select_args()
  87. #
  88. def make_select_args():
  89.     global select_args, select_handlers
  90.     rlist, wlist, xlist = [], [], []
  91.     rhandlers, whandlers, xhandlers = {}, {}, {}
  92.     for fd, mode, handler in fdlist:
  93.         if mode == 'r':
  94.             rlist.append(fd)
  95.             rhandlers[`fd`] = handler
  96.         if mode == 'w':
  97.             wlist.append(fd)
  98.             whandlers[`fd`] = handler
  99.         if mode == 'x':
  100.             xlist.append(fd)
  101.             xhandlers[`fd`] = handler
  102.     if rlist or wlist or xlist:
  103.         select_args = rlist, wlist, xlist
  104.         select_handlers = rhandlers, whandlers, xhandlers
  105.     else:
  106.         select_args = None
  107.         select_handlers = None
  108. #
  109. def do_select():
  110.     import select
  111.     reply = apply(select.select, select_args)
  112.     for mode in 0, 1, 2:
  113.         list = reply[mode]
  114.         for fd in list:
  115.             handler = select_handlers[mode][`fd`]
  116.             handler(fd, 'rwx'[mode])
  117.  
  118.  
  119. # Event processing main loop.
  120. # Return when there are no windows left, or when an unhandled
  121. # exception occurs.  (It is safe to restart the main loop after
  122. # an unsuccessful exit.)
  123. # Python's stdwin.getevent() turns WE_COMMAND/WC_CANCEL events
  124. # into KeyboardInterrupt exceptions; these are turned back in events.
  125. #
  126. recursion_level = 0 # Hack to make it reentrant
  127. def mainloop():
  128.     global recursion_level
  129.     recursion_level = recursion_level + 1
  130.     try:
  131.         stdwin_select_handler() # Process events already in queue
  132.         while 1:
  133.             if windows and not fdlist:
  134.                 while windows and not fdlist:
  135.                     try:
  136.                         event = stdwinq.getevent()
  137.                     except KeyboardInterrupt:
  138.                         event = (WE_COMMAND, \
  139.                              None, WC_CANCEL)
  140.                     dispatch(event)
  141.             elif windows and fdlist:
  142.                 fd = stdwin.fileno()
  143.                 if recursion_level == 1:
  144.                     registerfd(fd, 'r', stdwin_select_handler)
  145.                 try:
  146.                     while windows:
  147.                         do_select()
  148.                         stdwin_select_handler()
  149.                 finally:
  150.                     if recursion_level == 1:
  151.                         unregisterfd(fd)
  152.             elif fdlist:
  153.                 while fdlist and not windows:
  154.                     do_select()
  155.             else:
  156.                 break
  157.     finally:
  158.         recursion_level = recursion_level - 1
  159.  
  160.  
  161. # Check for events without ever blocking
  162. #
  163. def check():
  164.     stdwin_select_handler()
  165.     # XXX Should check for socket stuff as well
  166.  
  167.  
  168. # Handle stdwin events until none are left
  169. #
  170. def stdwin_select_handler(*args):
  171.     while 1:
  172.         try:
  173.             event = stdwinq.pollevent()
  174.         except KeyboardInterrupt:
  175.             event = (WE_COMMAND, None, WC_CANCEL)
  176.         if event is None:
  177.             break
  178.         dispatch(event)
  179.  
  180.  
  181. # Run a modal dialog loop for a window.  The dialog window must have
  182. # been registered first.  This prohibits most events (except size/draw
  183. # events) to other windows.  The modal dialog loop ends when the
  184. # dialog window unregisters itself.
  185. #
  186. passthrough = WE_SIZE, WE_DRAW
  187. beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU
  188. #
  189. def modaldialog(window):
  190.     if window not in windows:
  191.         raise ValueError, 'modaldialog window not registered'
  192.     while window in windows:
  193.         try:
  194.             event = stdwinq.getevent()
  195.         except KeyboardInterrupt:
  196.             event = WE_COMMAND, None, WC_CANCEL
  197.         etype, ewindow, edetail = event
  198.         if etype not in passthrough and ewindow <> window:
  199.             if etype in beeping:
  200.                 stdwin.fleep()
  201.             continue
  202.         dispatch(event)
  203.  
  204.  
  205. # Dispatch a single event.
  206. # Events for the no window in particular are sent to the active window
  207. # or to the last window that received an event (these hacks are for the
  208. # WE_LOST_SEL event, which is directed to no particular window).
  209. # Windows not in the windows list don't get their events:
  210. # events for such windows are silently ignored.
  211. #
  212. def dispatch(event):
  213.     global last_window
  214.     if event[1] == None:
  215.         active = stdwin.getactive()
  216.         if active: last_window = active
  217.     else:
  218.         last_window = event[1]
  219.     if last_window in windows:
  220.         last_window.dispatch(event)
  221.  
  222.  
  223. # Dialog base class
  224. #
  225. class Dialog:
  226.     #
  227.     def __init__(self, title):
  228.         self.window = stdwin.open(title)
  229.         self.window.dispatch = self.dispatch
  230.         register(self.window)
  231.     #
  232.     def close(self):
  233.         unregister(self.window)
  234.         del self.window.dispatch
  235.         self.window.close()
  236.     #
  237.     def dispatch(self, event):
  238.         etype, ewindow, edetail = event
  239.         if etype == WE_CLOSE:
  240.             self.close()
  241.  
  242.  
  243. # Standard modal dialogs
  244. # XXX implemented using stdwin dialogs for now
  245. #
  246. def askstr(prompt, default):
  247.     return stdwin.askstr(prompt, default)
  248. #
  249. def askync(prompt, yesorno):
  250.     return stdwin.askync(prompt, yesorno)
  251. #
  252. def askfile(prompt, default, new):
  253.     return stdwin.askfile(prompt, default, new)
  254. #
  255. def message(msg):
  256.     stdwin.message(msg)
  257.