changeset 63:6d522a046fda

Simplified the code a bit by moving events outside of enso.ui and making it and the quasimode no longer globally-accessible singletons (which got rid of a bunch of init/shutdown/accessor-cruft).
author Atul Varma <varmaa@toolness.com>
date Sat, 01 Mar 2008 23:32:59 -0600
parents f1564d6bb03b
children dff860373797
files enso/__init__.py enso/events.py enso/ui/__init__.py enso/ui/events.py enso/ui/quasimode/__init__.py
diffstat 5 files changed, 346 insertions(+), 458 deletions(-) [+]
line wrap: on
line diff
--- a/enso/__init__.py	Sat Mar 01 22:34:43 2008 -0600
+++ b/enso/__init__.py	Sat Mar 01 23:32:59 2008 -0600
@@ -37,18 +37,16 @@
     Initializes and runs Enso.
     """
 
-    import enso.plugins
-    import enso.ui
+    from enso import events, plugins, ui, config
 
-    enso.ui.init()
+    eventManager = events.EventManager( config.QUASIMODE_KEYCODE )
+
+    ui.init( eventManager )
     try:
-        enso.ui.events.eventManager.registerResponder(
-            enso.plugins.init,
-            "init"
-            )
+        eventManager.registerResponder( plugins.init, "init" )
         try:
-            enso.ui.run()
+            eventManager.run()
         finally:
-            enso.plugins.shutdown()
+            plugins.shutdown()
     finally:
-        enso.ui.shutdown()
+        ui.shutdown()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/enso/events.py	Sat Mar 01 23:32:59 2008 -0600
@@ -0,0 +1,307 @@
+# Copyright (c) 2008, Humanized, Inc.
+# All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#    1. Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#
+#    2. Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in the
+#       documentation and/or other materials provided with the distribution.
+#
+#    3. Neither the name of Enso nor the names of its contributors may
+#       be used to endorse or promote products derived from this
+#       software without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY Humanized, Inc. ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL Humanized, Inc. BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# ----------------------------------------------------------------------------
+#
+#   enso.events
+#
+# ----------------------------------------------------------------------------
+
+"""
+    The central event clearinghouse.
+
+    Wraps the InputManager to provide event handling for the user
+    interface.  User interface code, and indeed any client Python
+    code, can register event responders of several types (listed
+    below).  These responders can be added and removed in real time,
+    allowing the user interface to respond to events differently based
+    on system state; for example, a timer event handler that draws the
+    quasimode might be removed when not in the quasimode, to reduce
+    overhead when timer events occur and improve system performance.
+
+    The event manager implemented here does not implement a main event
+    loop; that is implemented the InputManager.  Calling the
+    run method of the event manager enters a main event loop that
+    calls the various on<event>() methods when events occur.  These
+    methods in turn call any responder functions registered for the
+    appropriate type of event.
+"""
+
+# ----------------------------------------------------------------------------
+# Imports
+# ----------------------------------------------------------------------------
+
+import logging
+from enso import input
+
+
+# ----------------------------------------------------------------------------
+# Constants
+# ----------------------------------------------------------------------------
+
+# A list of all possible types of events that event responders can be
+# registered for.
+EVENT_TYPES = [
+    "key",
+    "timer",
+    # LONGTERM TODO: Is "click" ever used?  Doesn't seem to be...
+    "click",
+    "dismissal",
+    "traymenu",
+    "idle",
+    "init",
+    "mousemove",
+    "somekey"
+    ]
+
+# Enso will consider the system idle after the following number of seconds.
+IDLE_TIMEOUT = 60*5
+
+
+# ----------------------------------------------------------------------------
+# EventManager class
+# ----------------------------------------------------------------------------
+
+class EventManager( input.InputManager ):
+    """
+    This class is the event-handling singleton, inheriting from the
+    input manager class.  It creates a dictionary of event responders,
+    and overrides the input manager's on<eventtype>() methods to call
+    every registered responder for <eventtype>.
+    """
+    
+    def __init__( self, quasimodeKeycode ):
+        """
+        Initializes the event manager, creates an internal dictionary
+        of responders.
+        """
+
+        input.InputManager.__init__( self, quasimodeKeycode )
+
+        # Copy the core event types to the dynamic event types list,
+        # which can be extended with the createEventType() method.
+        self._dynamicEventTypes = EVENT_TYPES[:]
+
+        self.__responders = {}
+        for evt in self._dynamicEventTypes:
+            self.__responders[evt] = []
+
+
+        self.__currIdleTime = 0
+
+    def createEventType( self, typeName ):
+        """
+        Creates a new event type to be responded to.
+
+        Implemented to allow for 'startQuasimode' and 'endQuasimode'
+        event types to be registered; it seems to be the logical way
+        for all event types to be dealt with.
+        """
+
+        assert typeName not in self._dynamicEventTypes        
+        self.__responders[typeName] = []
+        self._dynamicEventTypes.append( typeName )
+
+    def triggerEvent( self, eventType, *args, **kwargs ):
+        """
+        Used to (artificially or really) trigger an event type.
+        """
+
+        assert eventType in self._dynamicEventTypes
+        for func in self.__responders[ eventType ]:
+            func( *args, **kwargs )
+        
+
+    def getResponders( self, eventType ):
+        """
+        Returns a list of all responders of the given type.
+        """
+
+        assert eventType in self._dynamicEventTypes
+        return self.__responders[eventType]
+
+
+    def registerResponder( self, responderFunc, eventType ):
+        """
+        Registers a responder for event type eventType.
+        """
+
+        assert eventType in self._dynamicEventTypes
+        assert responderFunc not in self.getResponders( eventType )
+
+        responderList = self.__responders[ eventType ]
+        logging.debug( "Added a responder function!" )
+
+        # If this is a dismissal responder and we don't currently have
+        # any registered, enable mouse events so we're actually
+        # notified of dismissals via mouse input.
+        if eventType in ["dismissal","mousemove"]:
+            self.enableMouseEvents( True )
+
+        responderList.append( responderFunc )
+
+
+    def removeResponder( self, responderFunc ):
+        """
+        Removes responderFunc from the internal responder dictionary.
+
+        NOTE: Removes responderFunc from responding to ALL types of events.
+        """
+        
+        for eventType in self.__responders.keys():
+            responderList = self.__responders[ eventType ]
+            if responderFunc in responderList:
+                logging.debug( "Removed a responder function!" )
+                responderList.remove( responderFunc )
+
+        if eventType in ["dismissal","mousemove"]:
+            # If we're removing our only dismissal responder,
+            # disable mouse events since we only need to know
+            # about them for the purposes of dismissal events.
+            numMouseResponders = len( self.__responders[ "mousemove" ] )
+            numDismissResponders = len( self.__responders[ "dismissal" ] )
+            if (numMouseResponders+numDismissResponders) == 0:
+                self.enableMouseEvents( False )
+
+
+    def run( self ):
+        """
+        Runs the main event loop.
+        """
+
+        input.InputManager.run( self )
+    
+
+    # ----------------------------------------------------------------------
+    # Functions for transferring the existing event handlers to the more
+    # robust registerResponder method outlined above.
+    # ----------------------------------------------------------------------
+
+    def _onIdle( self ):
+        """
+        High-level event handler called whenever we haven't received
+        any useful input events for IDLE_TIMEOUT seconds.
+        """
+        
+        self.__currIdleTime = 0
+        for func in self.__responders[ "idle" ]:
+            func()
+
+    def onInit( self ):
+        """
+        Low-level event handler called as soon as the event manager
+        starts running.
+        """
+        
+        for func in self.__responders[ "init" ]:
+            func()
+
+    def onExitRequested( self ):
+        """
+        Called when another process wants us to exit gracefully.
+        """
+
+        logging.info( "Exit request received." )
+        self.stop()
+
+    def onTick( self, msPassed ):
+        """
+        Low-level event handler called at a regular interval.  The
+        number of milliseconds passed since the last onTick() call is
+        passed in, although this value may not be 100% accurate.
+        """
+        
+        self.__currIdleTime += msPassed
+
+        if self.__currIdleTime >= 1000*IDLE_TIMEOUT:
+            self._onIdle()
+        for func in self.__responders[ "timer" ]:
+            func( msPassed )
+
+    def onTrayMenuItem( self, menuId ):
+        """
+        Low-level event handler called whenever the user selects a
+        menu item on the popup menu of the Tray Icon.
+        """
+        
+        self._onDismissalEvent()
+        for func in self.__responders[ "traymenu" ]:
+            func( menuId )
+
+    def _onDismissalEvent( self ):
+        """
+        High-level event handler called whenever a keypress, mouse
+        movement, or mouse button click is made.
+        """
+        
+        self.__currIdleTime = 0
+        for func in self.__responders[ "dismissal" ]:
+            func()
+
+    def onKeypress( self, eventType, keyCode ):
+        """
+        Low-level event handler called whenever a quasimodal keypress
+        is made.
+        """
+
+        self.__currIdleTime = 0
+        self._onDismissalEvent()
+        for func in self.__responders[ "key" ]:
+            func( eventType, keyCode )
+
+        # The following message may be used by system tests.
+        logging.debug( "onKeypress: %s, %s" % (eventType, keyCode) )
+
+    def onMouseMove( self, x, y ):
+        """
+        Low-level event handler that deals with any mouse movement
+        event.  The absolute position of the mouse cursor on-screen is
+        passed in.
+        """
+        
+        self._onDismissalEvent()
+        for func in self.__responders[ "mousemove" ]:
+            func( x, y )
+
+    def onSomeMouseButton( self ):
+        """
+        Low-level event handler called whenever any mouse button is
+        pressed.
+        """
+        
+        self._onDismissalEvent()
+
+    def onSomeKey( self ):
+        """
+        Low-level event handler called whenever a non-quasimodal
+        keypress is made.
+        """
+
+        for func in self.__responders[ "somekey" ]:
+            func()
+        self._onDismissalEvent()
--- a/enso/ui/__init__.py	Sat Mar 01 22:34:43 2008 -0600
+++ b/enso/ui/__init__.py	Sat Mar 01 23:32:59 2008 -0600
@@ -43,7 +43,6 @@
 # Imports
 # ----------------------------------------------------------------------------
 
-from enso.ui import events
 from enso.ui import messages
 from enso.ui import quasimode
 from enso.ui import commands
@@ -54,8 +53,6 @@
 # Functions
 # ----------------------------------------------------------------------------
 
-_isUserInterfaceInited = False
-
 def _onEnterEventLoop():
     """
     Executed as soon as we enter the main event loop; at this point,
@@ -72,87 +69,33 @@
                                        fullXml = msgXml )
         messages.messageManager.newMessage( openingMsg )
 
-
-def _onExitEventLoop():
+def init( eventManager ):
     """
-    Executed as soon as we leave the main event loop.
+    Initializes the user interface module.  Do not call any functions
+    in this module until this function has been called.
     """
 
-    pass
-
+    commands.init()
+    messages.init( eventManager )
 
-def run():
-    """
-    Runs the user interface and does not return until the user
-    interface crashes or finishes properly.
-    """
+    # TODO: This is temporary; it looks weird now, but the Quasimode
+    # object is going to attach itself to the eventManager, so this
+    # Quasimode object won't go away when it's created.
+    quasimode.Quasimode( eventManager )
 
     # UI threads must be started upon the event manager's
     # initialization to ensure that the event manager is already
     # initialized and running when the other UI threads start.
-    events.eventManager.registerResponder(
+    eventManager.registerResponder(
         _onEnterEventLoop,
         "init"
         )
 
-    try:
-        events.eventManager.run()
-    finally:
-        _onExitEventLoop()
-
-
-def init():
-    """
-    Initializes the user interface module.  Do not call any functions
-    in this module until this function has been called.
-    """
-    
-    global _isUserInterfaceInited
-    
-    # Events must be initialized first, because other singletons may
-    # need to register responders.
-    events.init( enso.config.QUASIMODE_KEYCODE )
-
-    commands.init()
-    messages.init( events.eventManager )
-    quasimode.init()
-
-    _isUserInterfaceInited = True
-
-
-def isInitialized():
-    """
-    Returns whether or not this module is initialized.
-    """
-    
-    return _isUserInterfaceInited
-
-
-def stop():
-    """
-    Stops the user interface. This can be called multiple times, and
-    is also thread-safe.
-    """
-    
-    events.eventManager.stop()
-
-
 def shutdown():
     """
     Shuts down the user interface module.  Call this once you are done
     using any functions in this module.
     """
 
-    assert isInitialized(), ".shutdown() called before .init() in "\
-                            "UserInterface!"
-
-    # Events must be shutdown first, because it may contain lingering
-    # references to singletons that registered event responders.
-    events.shutdown()
-    
-    quasimode.shutdown()
     messages.shutdown()
     commands.shutdown()
-
-    global _isUserInterfaceInited
-    _isUserInterfaceInited = False
--- a/enso/ui/events.py	Sat Mar 01 22:34:43 2008 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,333 +0,0 @@
-# Copyright (c) 2008, Humanized, Inc.
-# All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-#    1. Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#
-#    2. Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#
-#    3. Neither the name of Enso nor the names of its contributors may
-#       be used to endorse or promote products derived from this
-#       software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY Humanized, Inc. ``AS IS'' AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL Humanized, Inc. BE LIABLE FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ----------------------------------------------------------------------------
-#
-#   enso.ui.events
-#
-# ----------------------------------------------------------------------------
-
-"""
-    The central event clearinghouse.
-
-    Wraps the InputManager to provide event handling for the user
-    interface.  User interface code, and indeed any client Python
-    code, can register event responders of several types (listed
-    below).  These responders can be added and removed in real time,
-    allowing the user interface to respond to events differently based
-    on system state; for example, a timer event handler that draws the
-    quasimode might be removed when not in the quasimode, to reduce
-    overhead when timer events occur and improve system performance.
-
-    The event manager implemented here does not implement a main event
-    loop; that is implemented the InputManager.  Calling the
-    run method of the event manager enters a main event loop that
-    calls the various on<event>() methods when events occur.  These
-    methods in turn call any responder functions registered for the
-    appropriate type of event.
-"""
-
-# ----------------------------------------------------------------------------
-# Imports
-# ----------------------------------------------------------------------------
-
-import logging
-from enso import input
-
-
-# ----------------------------------------------------------------------------
-# Constants
-# ----------------------------------------------------------------------------
-
-# A list of all possible types of events that event responders can be
-# registered for.
-EVENT_TYPES = [
-    "key",
-    "timer",
-    # LONGTERM TODO: Is "click" ever used?  Doesn't seem to be...
-    "click",
-    "dismissal",
-    "traymenu",
-    "idle",
-    "init",
-    "mousemove",
-    "somekey"
-    ]
-
-# Enso will consider the system idle after the following number of seconds.
-IDLE_TIMEOUT = 60*5
-
-
-# ----------------------------------------------------------------------------
-# Enso's Main Application Loop Class
-# ----------------------------------------------------------------------------
-
-class _TheEventManager( input.InputManager ):
-    """
-    This class is the event-handling singleton, inheriting from the
-    input manager class.  It creates a dictionary of event responders,
-    and overrides the input manager's on<eventtype>() methods to call
-    every registered responder for <eventtype>.
-    """
-    
-    def __init__( self, quasimodeKeycode ):
-        """
-        Initializes the event manager, creates an internal dictionary
-        of responders.
-        """
-
-        input.InputManager.__init__( self, quasimodeKeycode )
-
-        # Copy the core event types to the dynamic event types list,
-        # which can be extended with the createEventType() method.
-        self._dynamicEventTypes = EVENT_TYPES[:]
-
-        self.__responders = {}
-        for evt in self._dynamicEventTypes:
-            self.__responders[evt] = []
-
-
-        self.__currIdleTime = 0
-
-    def createEventType( self, typeName ):
-        """
-        Creates a new event type to be responded to.
-
-        Implemented to allow for 'startQuasimode' and 'endQuasimode'
-        event types to be registered; it seems to be the logical way
-        for all event types to be dealt with.
-        """
-
-        assert typeName not in self._dynamicEventTypes        
-        self.__responders[typeName] = []
-        self._dynamicEventTypes.append( typeName )
-
-    def triggerEvent( self, eventType, *args, **kwargs ):
-        """
-        Used to (artificially or really) trigger an event type.
-        """
-
-        assert eventType in self._dynamicEventTypes
-        for func in self.__responders[ eventType ]:
-            func( *args, **kwargs )
-        
-
-    def getResponders( self, eventType ):
-        """
-        Returns a list of all responders of the given type.
-        """
-
-        assert eventType in self._dynamicEventTypes
-        return self.__responders[eventType]
-
-
-    def registerResponder( self, responderFunc, eventType ):
-        """
-        Registers a responder for event type eventType.
-        """
-
-        assert eventType in self._dynamicEventTypes
-        assert responderFunc not in self.getResponders( eventType )
-
-        responderList = self.__responders[ eventType ]
-        logging.debug( "Added a responder function!" )
-
-        # If this is a dismissal responder and we don't currently have
-        # any registered, enable mouse events so we're actually
-        # notified of dismissals via mouse input.
-        if eventType in ["dismissal","mousemove"]:
-            self.enableMouseEvents( True )
-
-        responderList.append( responderFunc )
-
-
-    def removeResponder( self, responderFunc ):
-        """
-        Removes responderFunc from the internal responder dictionary.
-
-        NOTE: Removes responderFunc from responding to ALL types of events.
-        """
-        
-        for eventType in self.__responders.keys():
-            responderList = self.__responders[ eventType ]
-            if responderFunc in responderList:
-                logging.debug( "Removed a responder function!" )
-                responderList.remove( responderFunc )
-
-        if eventType in ["dismissal","mousemove"]:
-            # If we're removing our only dismissal responder,
-            # disable mouse events since we only need to know
-            # about them for the purposes of dismissal events.
-            numMouseResponders = len( self.__responders[ "mousemove" ] )
-            numDismissResponders = len( self.__responders[ "dismissal" ] )
-            if (numMouseResponders+numDismissResponders) == 0:
-                self.enableMouseEvents( False )
-
-
-    def run( self ):
-        """
-        Runs Enso's main event loop.
-
-        NOTE: This call enters a C++ "while" loop that does not stop
-        until some code (inside of an event responder) calls the
-        stop() method.
-
-        This method releases the Global Enso Lock so that other
-        threads can use Enso while we're waiting for events; as soon
-        as an event is triggered and we re-enter Python code via a
-        low-level event handler, we re-acquire the Global Enso Lock.
-        """
-
-        input.InputManager.run( self )
-    
-
-    # ----------------------------------------------------------------------
-    # Functions for transfering the existing event handlers to the more
-    # robust registerResponder method outlined above.
-    # ----------------------------------------------------------------------
-
-    def _onIdle( self ):
-        """
-        High-level event handler called whenever we haven't received
-        any useful input events for IDLE_TIMEOUT seconds.
-        """
-        
-        self.__currIdleTime = 0
-        for func in self.__responders[ "idle" ]:
-            func()
-
-    def onInit( self ):
-        """
-        Low-level event handler called as soon as the event manager
-        starts running.
-        """
-        
-        for func in self.__responders[ "init" ]:
-            func()
-
-    def onExitRequested( self ):
-        """
-        Called when another process wants us to exit gracefully.
-        """
-
-        logging.info( "Exit request received." )
-        self.stop()
-
-    def onTick( self, msPassed ):
-        """
-        Low-level event handler called at a regular interval.  The
-        number of milliseconds passed since the last onTick() call is
-        passed in, although this value may not be 100% accurate.
-        """
-        
-        self.__currIdleTime += msPassed
-
-        if self.__currIdleTime >= 1000*IDLE_TIMEOUT:
-            self._onIdle()
-        for func in self.__responders[ "timer" ]:
-            func( msPassed )
-
-    def onTrayMenuItem( self, menuId ):
-        """
-        Low-level event handler called whenever the user selects a
-        menu item on the popup menu of the Tray Icon.
-        """
-        
-        self._onDismissalEvent()
-        for func in self.__responders[ "traymenu" ]:
-            func( menuId )
-
-    def _onDismissalEvent( self ):
-        """
-        High-level event handler called whenever a keypress, mouse
-        movement, or mouse button click is made.
-        """
-        
-        self.__currIdleTime = 0
-        for func in self.__responders[ "dismissal" ]:
-            func()
-
-    def onKeypress( self, eventType, keyCode ):
-        """
-        Low-level event handler called whenever a quasimodal keypress
-        is made.
-        """
-
-        self.__currIdleTime = 0
-        self._onDismissalEvent()
-        for func in self.__responders[ "key" ]:
-            func( eventType, keyCode )
-
-        # The following message may be used by system tests.
-        logging.debug( "onKeypress: %s, %s" % (eventType, keyCode) )
-
-    def onMouseMove( self, x, y ):
-        """
-        Low-level event handler that deals with any mouse movement
-        event.  The absolute position of the mouse cursor on-screen is
-        passed in.
-        """
-        
-        self._onDismissalEvent()
-        for func in self.__responders[ "mousemove" ]:
-            func( x, y )
-
-    def onSomeMouseButton( self ):
-        """
-        Low-level event handler called whenever any mouse button is
-        pressed.
-        """
-        
-        self._onDismissalEvent()
-
-    def onSomeKey( self ):
-        """
-        Low-level event handler called whenever a non-quasimodal
-        keypress is made.
-        """
-
-        for func in self.__responders[ "somekey" ]:
-            func()
-        self._onDismissalEvent()
-
-
-# ----------------------------------------------------------------------------
-# Module Initialization
-# ----------------------------------------------------------------------------
-
-eventManager = None
-
-def init( quasimodeKeycode ):
-    global eventManager
-
-    eventManager = _TheEventManager( quasimodeKeycode )
-
-def shutdown():
-    global eventManager
-
-    eventManager = None
--- a/enso/ui/quasimode/__init__.py	Sat Mar 01 22:34:43 2008 -0600
+++ b/enso/ui/quasimode/__init__.py	Sat Mar 01 23:32:59 2008 -0600
@@ -51,7 +51,6 @@
 import weakref
 import logging
 
-from enso.ui import events
 from enso.ui import commands
 from enso.ui import messages
 from enso import config
@@ -72,7 +71,7 @@
 # TheQuasimode
 # ----------------------------------------------------------------------------
 
-class _TheQuasimode:
+class Quasimode:
     """
     Encapsulates the command quasimode state and event-handling.
 
@@ -85,7 +84,7 @@
     and separation of event handling into the two states.
     """
 
-    def __init__( self ):
+    def __init__( self, eventManager ):
         """
         Initialize the quasimode.
         """
@@ -116,31 +115,31 @@
         # display, or only the description and user text.
         self.__nextRedrawIsFull = False
 
+        self.__eventMgr = eventManager
+
         # Register a key event responder, so that the quasimode can
         # actually respond to quasimode events.
-        eventMan = events.eventManager
-        eventMan.registerResponder( self.onKeyEvent, "key" )
+        self.__eventMgr.registerResponder( self.onKeyEvent, "key" )
 
         # Creates new event types that code can subscribe to, to find out
         # when the quasimode (or mode) is started and completed.
-        eventMan.createEventType( "startQuasimode" )
-        eventMan.createEventType( "endQuasimode" )
+        self.__eventMgr.createEventType( "startQuasimode" )
+        self.__eventMgr.createEventType( "endQuasimode" )
 
         # Read settings from config file: are we modal?
         # What key activates the quasimode?
         self.quasimodeKeycode = config.QUASIMODE_KEYCODE
         self.__isModal = config.IS_QUASIMODE_MODAL
 
-        # Pass these settings on to the low-level C code:
-        eventMan.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_START,
-                                      self.quasimodeKeycode )
-        eventMan.setModality( self.__isModal )
+        self.__eventMgr.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_START,
+                                             self.quasimodeKeycode )
+        self.__eventMgr.setModality( self.__isModal )
 
         # Register "enter" and "escape" as exit keys:
-        eventMan.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_END,
-                                      input.KEYCODE_RETURN )
-        eventMan.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_CANCEL,
-                                      input.KEYCODE_ESCAPE )
+        self.__eventMgr.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_END,
+                                             input.KEYCODE_RETURN )
+        self.__eventMgr.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_CANCEL,
+                                             input.KEYCODE_ESCAPE )
 
 
     def getQuasimodeKey( self ):
@@ -155,9 +154,8 @@
         
         self.quasimodeKeycode = keycode
 
-        eventMan = events.eventManager
-        eventMan.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_START,
-                                      keycode )
+        self.__eventMgr.setQuasimodeKeycode( input.KEYCODE_QUASIMODE_START,
+                                             keycode )
 
     def isModal( self ):
         return self.__isModal
@@ -167,8 +165,7 @@
         config.IS_QUASIMODE_MODAL = isModal
         
         self.__isModal = isModal
-        eventMan = events.eventManager
-        eventMan.setModality( isModal )
+        self.__eventMgr.setModality( isModal )
 
     def getSuggestionList( self ):
         return self.__suggestionList
@@ -266,10 +263,9 @@
             logging.info( "Created a new quasimode window!" )
             self.__quasimodeWindow = TheQuasimodeWindow()
 
-        eventMan = events.eventManager
-        eventMan.triggerEvent( "startQuasimode" )
+        self.__eventMgr.triggerEvent( "startQuasimode" )
         
-        eventMan.registerResponder( self.__onTick, "timer" )
+        self.__eventMgr.registerResponder( self.__onTick, "timer" )
 
         self._inQuasimode = True
         self.__needsRedraw = True
@@ -312,9 +308,8 @@
 
         # The quasimode has terminated; remove the timer responder
         # function as an event responder.
-        eventMan = events.eventManager
-        eventMan.triggerEvent( "endQuasimode" )
-        eventMan.removeResponder( self.__onTick )
+        self.__eventMgr.triggerEvent( "endQuasimode" )
+        self.__eventMgr.removeResponder( self.__onTick )
 
         # LONGTERM TODO: Determine whether deleting or hiding is better.
         logging.info( "Deleting the quasimode window." )
@@ -412,25 +407,3 @@
             caption = ""
 
         return caption
-
-
-# ----------------------------------------------------------------------------
-# Module Initilization
-# ----------------------------------------------------------------------------
-
-_quasimode = None
-
-def init():
-    global _quasimode
-
-    logging.info( "Initing the Quasimode." )
-    _quasimode = _TheQuasimode()
-
-def shutdown():
-    global _quasimode
-
-    logging.info( "Shutting down the Quasimode." )
-    _quasimode = None
-
-def get():
-    return _quasimode