summaryrefslogtreecommitdiffstats
path: root/Lib/stdwin/mainloop.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-11-26 09:17:19 (GMT)
committerGuido van Rossum <guido@python.org>1992-11-26 09:17:19 (GMT)
commit18fc5696c8be30b56485a20dc48f7f683b472f79 (patch)
tree97da7e7f67ca99491939ab379614cd64a4f51505 /Lib/stdwin/mainloop.py
parentc89705d6975ffb1e4a3764f4f36bab339f969e8f (diff)
downloadcpython-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-xLib/stdwin/mainloop.py171
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)