home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
fnb101.zip
/
Lib
/
site-packages
/
Fnorb
/
orb
/
TkReactor.py
< prev
next >
Wrap
Text File
|
1999-06-28
|
8KB
|
287 lines
#!/usr/bin/env python
#############################################################################
# Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999
# All Rights Reserved.
#
# The software contained on this media is the property of the DSTC Pty
# Ltd. Use of this software is strictly in accordance with the
# license agreement in the accompanying LICENSE.HTML file. If your
# distribution of this software does not contain a LICENSE.HTML file
# then you have no rights to use this software in any manner and
# should contact DSTC at the address below to determine an appropriate
# licensing arrangement.
#
# DSTC Pty Ltd
# Level 7, GP South
# Staff House Road
# University of Queensland
# St Lucia, 4072
# Australia
# Tel: +61 7 3365 4310
# Fax: +61 7 3365 4311
# Email: enquiries@dstc.edu.au
#
# This software is being provided "AS IS" without warranty of any
# kind. In no event shall DSTC Pty Ltd be liable for damage of any
# kind arising out of or in connection with the use or performance of
# this software.
#
# Project: Fnorb
# File: $Source: /units/arch/src/Fnorb/orb/RCS/TkReactor.py,v $
# Version: @(#)$RCSfile: TkReactor.py,v $ $Revision: 1.15 $
#
#############################################################################
""" A Reactor for use with 'tkinter'.
'tkinter' (and 'Tk' itself) are NOT thread-safe, and therefore this module
assumes a single-threaded environment.
"""
# The Python module for Tk 4.1 and upwards is "_tkinter", for Tk 4.0 it is
# "tkinter" 8^(
try:
import _tkinter
except ImportError:
import tkinter; _tkinter = tkinter
# Fnorb modules.
import Reactor
def TkReactor_init():
""" Initialise the TkReactor.
There can only be one instance of any concrete reactor class per process.
"""
try:
reactor = TkReactor()
except Reactor.Reactor, reactor:
pass
return reactor
class TkReactor(Reactor.Reactor):
""" The TkReactor.
The TkReactor uses the Tk event loop to dispatch Fnorb events.
"""
def __init__(self):
""" Constructor. """
# There can be at most one instance of any concrete reactor class per
# process.
if Reactor.Reactor._instance is not None:
# A reactor already exists.
raise Reactor.Reactor._instance
Reactor.Reactor._instance = self
# A dictionary of all registered event handlers. All handles in the
# TkReactor are actually just file descriptors.
self.__handlers = {} # {Handle: (EventHandler, Mask)}
return
#########################################################################
# Reactor interface.
#########################################################################
def register_handler(self, handler, mask):
""" Register an event handler. """
# Get the event handler's underlying I/O handle.
handle = handler.handle()
# If the handler is already registered then update the mask.
try:
# Find the event handler associated with the handle.
(handler, handler_mask) = self.__handlers[handle]
# Update the mask.
handler_mask = handler_mask | mask
# Otherwise, add the new handler.
except KeyError:
handler_mask = mask
# Do the add/update.
self.__handlers[handle] = (handler, handler_mask)
# Register with Tk.
self.__register_Tk_handler(handle, handler_mask)
return
def unregister_handler(self, handler, mask):
""" Withdraw a handler's registration. """
# Get the event handler's underlying I/O handle.
handle = handler.handle()
try:
# Find the event handler associated with the handle.
(handler, handler_mask) = self.__handlers[handle]
# Update the mask.
handler_mask = handler_mask & ~mask
# If the mask is now zero (ie. the handler is no longer interested
# in *any* events) then delete the handler.
if handler_mask == 0:
# Remove the handler from Tk.
_tkinter.deletefilehandler(handle)
# Delete it!
del self.__handlers[handle]
# Otherwise, update the handler's mask and re-register with Tk.
else:
# Update the handler's mask.
self.__handlers[handle] = (handler, handler_mask)
# Re-register with Tk.
self.__register_Tk_handler(handle, handler_mask)
# Ignore any attempts to un-register something that wasn't registerd!
except KeyError:
pass
return
def start_event_loop(self, timeout=None):
""" Start the event loop. """
# Enter the Tk mainloop (ie. Tk will dispatch the events).
_tkinter.mainloop()
# Close all registered handlers.
self.__close_all_handlers()
return
def stop_event_loop(self):
""" Stop the event loop. """
# Quit the Tk mainloop.
_tkinter.quit()
return
def do_one_event(self):
""" Dispatch a single event. """
_tkinter.dooneevent()
return
# The following two methods are provided to allow Fnorb events to be
# handled in other event loops.
def handles(self):
""" Return the read/write/exception handles for registered handlers.
The return value is a tuple in the form:-
([ReadHandles], [WriteHandles], [ExceptionHandles])
"""
return self.__get_handles()
def handle_one_event(self, handle, tk_mask):
""" Handle a single Tk event. """
self.__handle_Tk_event(handle, tk_mask)
return
#########################################################################
# Private interface.
#########################################################################
def __get_handles(self):
""" Return the read/write/exception handles for registered handlers.
The return value is a tuple in the form:-
([ReadHandles], [WriteHandles], [ExceptionHandles])
"""
iwtd = {}
owtd = {}
ewtd = {}
for handle in self.__handlers.keys():
# Find the event handler associated with the handle.
(handler, mask) = self.__handlers[handle]
if mask & Reactor.READ:
iwtd[handle] = None
if mask & Reactor.WRITE:
owtd[handle] = None
# Listen for errors on all handles.
ewtd[handle] = None
return (iwtd.keys(), owtd.keys(), ewtd.keys())
def __handle_Tk_event(self, handle, tk_mask):
""" Handle an event. """
# Translate between Tk and Fnorb event masks.
mask = 0x0
if tk_mask & _tkinter.READABLE:
mask = mask | Reactor.READ
if tk_mask & _tkinter.WRITABLE:
mask = mask | Reactor.WRITE
if tk_mask & _tkinter.EXCEPTION:
mask = mask | Reactor.EXCEPTION
# Find the event handler associated with the handle.
(handler, handler_mask) = self.__handlers[handle]
# Handler callback.
handler.handle_event(mask)
return
def __register_Tk_handler(self, handle, mask):
""" Register a file handler with Tk. """
# Translate between Fnorb and Tk event masks (we are always interested
# in exceptions!).
tk_mask = _tkinter.EXCEPTION
if mask & Reactor.READ:
tk_mask = tk_mask | _tkinter.READABLE
if mask & Reactor.WRITE:
tk_mask = tk_mask | _tkinter.WRITABLE
# Register with Tk.
_tkinter.createfilehandler(handle, tk_mask, self.__handle_Tk_event)
return
def __close_all_handlers(self):
""" Close all registered handlers. """
# We work on a copy of the list, 'cos the handlers will most likely
# call 'unregister_handler' in their 'close' method.
for (handler, mask) in self.__handlers.values():
# Handler callback.
handler.handle_close()
return
#############################################################################