diff options
author | Guido van Rossum <guido@python.org> | 1992-11-26 09:17:19 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1992-11-26 09:17:19 (GMT) |
commit | 18fc5696c8be30b56485a20dc48f7f683b472f79 (patch) | |
tree | 97da7e7f67ca99491939ab379614cd64a4f51505 /Lib/stdwin/mainloop.py | |
parent | c89705d6975ffb1e4a3764f4f36bab339f969e8f (diff) | |
download | cpython-18fc5696c8be30b56485a20dc48f7f683b472f79.zip cpython-18fc5696c8be30b56485a20dc48f7f683b472f79.tar.gz cpython-18fc5696c8be30b56485a20dc48f7f683b472f79.tar.bz2 |
* mainloop.py: added facility for calling select(). Also added
embryonic facility for pseudo-modal dialogs.
* stdwinevents.py: added modifier masks for key/mouse events
* renamed exceptions in nntplib.py
* Changed string.join() to call string.joinfields() to profit of
strop.joinfields()
Diffstat (limited to 'Lib/stdwin/mainloop.py')
-rwxr-xr-x | Lib/stdwin/mainloop.py | 171 |
1 files changed, 166 insertions, 5 deletions
diff --git a/Lib/stdwin/mainloop.py b/Lib/stdwin/mainloop.py index 0cf5bde..ab8ad3a 100755 --- a/Lib/stdwin/mainloop.py +++ b/Lib/stdwin/mainloop.py @@ -13,6 +13,11 @@ from stdwinevents import * windows = [] +# Last window that ever received an event +# +last_window = None + + # Function to register a window. # def register(win): @@ -28,6 +33,9 @@ def register(win): # (this is useful for cleanup actions). # def unregister(win): + global last_window + if win == last_window: + last_window = None if win in windows: windows.remove(win) # Not in 0.9.1 # 0.9.1 solution: @@ -49,6 +57,65 @@ def anywindow(): return None +# NEW: register any number of file descriptors +# +fdlist = [] +select_args = None +select_handlers = None +# +def registerfd(fd, mode, handler): + if mode not in ('r', 'w', 'x'): + raise ValueError, 'mode must be r, w or x' + if type(fd) <> type(0): + fd = fd.fileno() # If this fails it's not a proper select arg + for i in range(len(fdlist)): + if fdlist[i][:2] == (fd, mode): + raise ValueError, \ + '(fd, mode) combination already registered' + fdlist.append((fd, mode, handler)) + make_select_args() +# +def unregisterfd(fd, *args): + if type(fd) <> type(0): + fd = fd.fileno() # If this fails it's not a proper select arg + args = (fd,) + args + n = len(args) + for i in range(len(fdlist)): + if fdlist[i][:n] == args: + del fdlist[i] + make_select_args() +# +def make_select_args(): + global select_args, select_handlers + rlist, wlist, xlist = [], [], [] + rhandlers, whandlers, xhandlers = {}, {}, {} + for fd, mode, handler in fdlist: + if mode == 'r': + rlist.append(fd) + rhandlers[`fd`] = handler + if mode == 'w': + wlist.append(fd) + whandlers[`fd`] = handler + if mode == 'x': + xlist.append(fd) + xhandlers[`fd`] = handler + if rlist or wlist or xlist: + select_args = rlist, wlist, xlist + select_handlers = rhandlers, whandlers, xhandlers + else: + select_args = None + select_handlers = None +# +def do_select(): + import select + reply = apply(select.select, select_args) + for mode in 0, 1, 2: + list = reply[mode] + for fd in list: + handler = select_handlers[mode][`fd`] + handler(fd, 'rwx'[mode]) + + # Event processing main loop. # Return when there are no windows left, or when an unhandled # exception occurs. (It is safe to restart the main loop after @@ -57,17 +124,111 @@ def anywindow(): # into KeyboardInterrupt exceptions; these are turned back in events. # def mainloop(): - while windows: + stdwin_select_handler() # Process events already in stdwin queue + fd = stdwin.fileno() + while 1: + if windows: + registerfd(fd, 'r', stdwin_select_handler) + try: + while windows: + do_select() + stdwin_select_handler() + finally: + unregisterfd(fd) + elif fdlist: + while fdlist and not windows: + do_select() + else: + break + + +# Handle stdwin events until none are left +# +def stdwin_select_handler(*args): + while 1: + try: + event = stdwinq.pollevent() + except KeyboardInterrupt: + event = (WE_COMMAND, None, WC_CANCEL) + if event is None: + break + dispatch(event) + + +# Run a modal dialog loop for a window. The dialog window must have +# been registered first. This prohibits most events (except size/draw +# events) to other windows. The modal dialog loop ends when the +# dialog window unregisters itself. +# +passthrough = WE_SIZE, WE_DRAW +beeping = WE_MOUSE_DOWN, WE_COMMAND, WE_CHAR, WE_KEY, WE_CLOSE, WE_MENU +# +def modaldialog(window): + if window not in windows: + raise ValueError, 'modaldialog window not registered' + while window in windows: try: - dispatch(stdwinq.getevent()) + event = stdwinq.getevent() except KeyboardInterrupt: - dispatch(WE_COMMAND, stdwin.getactive(), WC_CANCEL) + event = WE_COMMAND, None, WC_CANCEL + etype, ewindow, edetail = event + if etype not in passthrough and ewindow <> window: + if etype in beeping: + stdwin.fleep() + continue + dispatch(event) # Dispatch a single event. +# Events for the no window in particular are sent to the active window +# or to the last window that received an event (these hacks are for the +# WE_LOST_SEL event, which is directed to no particular window). # Windows not in the windows list don't get their events: # events for such windows are silently ignored. # def dispatch(event): - if event[1] in windows: - event[1].dispatch(event) + global last_window + if event[1] == None: + active = stdwin.getactive() + if active: last_window = active + else: + last_window = event[1] + if last_window in windows: + last_window.dispatch(event) + + +# Dialog base class +# +class Dialog: + # + def init(self, title): + self.window = stdwin.open(title) + self.window.dispatch = self.dispatch + register(self.window) + return self + # + def close(self): + unregister(self.window) + del self.window.dispatch + self.window.close() + # + def dispatch(self, event): + etype, ewindow, edetail = event + if etype == WE_CLOSE: + self.close() + + +# Standard modal dialogs +# XXX implemented using stdwin dialogs for now +# +def askstr(prompt, default): + return stdwin.askstr(prompt, default) +# +def askync(prompt, yesorno): + return stdwin.askync(prompt, yesorno) +# +def askfile(prompt, default, new): + return stdwin.askfile(prompt, default, new) +# +def message(msg): + stdwin.message(msg) |