commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r8391 - in trunk/gnue-forms/src: . GFObjects uidrivers/_base


From: johannes
Subject: [gnue] r8391 - in trunk/gnue-forms/src: . GFObjects uidrivers/_base
Date: Fri, 7 Apr 2006 04:21:51 -0500 (CDT)

Author: johannes
Date: 2006-04-07 04:21:49 -0500 (Fri, 07 Apr 2006)
New Revision: 8391

Modified:
   trunk/gnue-forms/src/GFForm.py
   trunk/gnue-forms/src/GFInstance.py
   trunk/gnue-forms/src/GFObjects/__init__.py
   trunk/gnue-forms/src/uidrivers/_base/UIdriver.py
Log:
findAndChangeFocus() first searches within the visible containers. Some 
cleanup and pep8-ification


Modified: trunk/gnue-forms/src/GFForm.py
===================================================================
--- trunk/gnue-forms/src/GFForm.py      2006-04-07 06:55:42 UTC (rev 8390)
+++ trunk/gnue-forms/src/GFForm.py      2006-04-07 09:21:49 UTC (rev 8391)
@@ -1,6 +1,9 @@
+# GNU Enterprise Forms - GF Object Hierarchy - Form
 #
-# This file is part of GNU Enterprise.
+# Copyright 2001-2006 Free Software Foundation
 #
+# This file is part of GNU Enterprise
+#
 # GNU Enterprise is free software; you can redistribute it
 # and/or modify it under the terms of the GNU General Public
 # License as published by the Free Software Foundation; either
@@ -16,21 +19,15 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place
 # - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2000-2006 Free Software Foundation
-#
-# DESCRIPTION:
-# Class that contains the internal python object representation of a GNUe Form
-# built from GFObjects
-#
-# NOTES:
-#
 # $Id$
+"""
+Class that contains the internal python object representation of a GNUe Form
+built from GFObjects
+"""
 
 import sys
-import string
-import traceback
 
-from gnue.common.apps import i18n
+from gnue.common.apps import i18n, errors
 from gnue.common import events
 from gnue.common.datasources.Exceptions import ConnectionError as DBError
 from gnue.common.definitions.GRootObj import GRootObj
@@ -41,1166 +38,1188 @@
 from gnue.forms import GFParser
 from gnue.common.utils import CaselessDict
 
+# =============================================================================
+# Exceptions
+# =============================================================================
 
-#-----------------------------------------------------------------------------
-# Defines which objects are "Tab Stops"
-#-----------------------------------------------------------------------------
-TabStops = ('GFEntry','GFButton')
+class MinimumLengthError(errors.UserError):
+    def __init__ (self, min_length):
+        msg = u_("Minimum required length %d") % min_length
+        errors.UserError.__init__(self, msg)
 
 
-#-----------------------------------------------------------------------------
-# GFForm
-#-----------------------------------------------------------------------------
+
+# =============================================================================
+# Implementation of the form tag
+# =============================================================================
+
 class GFForm(GRootObj, GFObj, events.EventAware):
-  """
-  Contains the internal python object representation of a GNUe Form
-  built from GFObjects
-  """
+    """
+    Contains the internal python object representation of a GNUe Form built
+    from GFObjects.
+    """
 
-  #---------------------------------------------------------------------------
-  # instance is passed into the initializer so that
-  # designer can pass that in
-  #---------------------------------------------------------------------------
-  def __init__(self, parent=None, instance=None):
-  # TODO: with a little tweaking we can now stop passing  
GFParser.getXMLelements
-    GRootObj.__init__(self, 'form', GFParser.getXMLelements, GFParser)
-    GFObj.__init__(self, parent)
+    # -------------------------------------------------------------------------
+    # Constructor
+    # -------------------------------------------------------------------------
 
-    self._type = "GFForm"
-    self.name="__main__"
+    def __init__(self, parent=None, instance=None):
 
-    # Datasources referced by this form
-    self._datasourceDictionary = {}
+        GRootObj.__init__(self, 'form', GFParser.getXMLelements, GFParser)
+        GFObj.__init__(self, parent, 'GFForm')
 
-    # Dictionary to locate named triggers
-    self._triggerDictionary = {}
+        self.name = "__main__"
 
-    # Insert/Overwrite mode
-    self._insertMode = True
+        # Datasources referced by this form
+        self._datasourceDictionary = {}
 
-    # Focus information
-    self._currentPage = None
-    self._currentBlock = None
-    self._currentEntry = None
+        # Dictionary to locate named triggers
+        self._triggerDictionary = {}
 
-    # set
-    self._instance = instance
-    self._app = self._instance #TODO: Imports are broken do to
-                               #TODO: switch from _app to _instance
+        # Insert/Overwrite mode
+        self._insertMode = True
 
-    # Hackery until proper layout support is added
-    self._standardnamespaces = {'Char': 'GNUe:Forms:Char'}
+        # Focus information
+        self._currentPage = None
+        self._currentBlock = None
+        self._currentEntry = None
 
-    # The "None" init gives datasources time to setup master/detail
-    self._inits = [self.primaryInit, None, self.secondaryInit]
+        self._instance = instance
 
-    #
-    # Trigger support
-    #
-    self._triggerns = {}
-    self._triggerGlobal = True # Put this object into the global namespace by 
it's name
+        # Hackery until proper layout support is added
+        self._standardnamespaces = {'Char': 'GNUe:Forms:Char'}
 
-    self._validTriggers = { 'ON-STARTUP':     'On-Startup',
-                            'ON-ACTIVATION':  'On-Activation',
-                            'PRE-EXIT':       'Pre-Exit',
-                            'ON-EXIT':        'On-Exit',
-                            'PRE-COMMIT':     'Pre-Commit',
-                            'POST-COMMIT':    'Post-Commit' }
+        # The "None" init gives datasources time to setup master/detail
+        self._inits = [self.phase_1_init, None, self.phase_3_init]
 
-    self._triggerFunctions = {'setFocus':{'function':self.triggerSetFocus,
-                                          'global': True,
-                                          },
-                              
'getAuthenticatedUser':{'function':self.triggerGetAuthenticatedUser,
-                                                      'global': True,
-                                                      },
-                              'setTitle':{'function':self.triggerSetTitle,
-                                                      'global': True,
-                                                      },
-#                               
'getCurrentEntry':{'function':self.triggerGetCurrentEntry,
-#                                                  'global': True,
-#                                                  },
-                              
'getCurrentBlockName':{'function':self.triggerGetCurrentBlockName,
-                                                 'global': True,
-                                                 },
-#                               
'getCurrentPage':{'function':self.triggerGetCurrentPage,
-#                                                 'global': True,
-#                                                },
-                              
'setStatusText':{'function':self.triggerSetStatusText,
-                                               'global': True,
-                                               },
-                              'getParameter':{'function':self.getParameter,
-                                              'global': True,
-                                              },
-                              
'setParameter':{'function':self.triggerSetParameter,
-                                              'global': True,
-                                              },
-                              
'showMessage':{'function':self.triggerShowMessageBox,
-                                             'global': True,
-                                             },
-                              'messageBox': {'function':self.triggerMessageBox,
-                                             'global': True
-                                             },
-                              'commit':{'function':self.triggerCommit,
-                                        'global': True,
-                                        },
-                              'rollback':{'function':self.rollback,
-                                        'global': True,
-                                        },
-                              'close':{'function':self.triggerClose,
-                                       'global': True,
-                                       },
-                              'beep':{'function':self.triggerBeep,
-                                       'global': True,
-                                       },
-                              'getFeature':{'function':self.triggerGetFeature,
-                                            'global': True,
-                                            },
-                              'setFeature':{'function':self.triggerSetFeature,
-                                            'global': True,
-                                            },
-                              'runForm':{'function':self.triggerRunForm,
-                                         'global': True,
-                                         } ,
-                              'runReport':{'function':self.triggerRunReport,
-                                         'global': True,
-                                         } ,
-                              
'activateDialog':{'function':self.triggerActivateDialog,
-                                                'global': True,
-                                                } ,
-                              'activateTrigger':{'function':self.fireTrigger,
-                                                'global': True,
-                                                } ,
-                              'initQuery':{'function':self.initQuery,
-                                           },
-                              }
+        # Trigger support
+        self._triggerns = {}
+        self._triggerGlobal = True
 
-    self._features = {
-      'GUI:MENUBAR:SUPPRESS': False,
-      'GUI:TOOLBAR:SUPPRESS': False,
-      'GUI:STATUSBAR:SUPPRESS': False,
-    }
+        self._validTriggers = {
+            'ON-STARTUP':    'On-Startup',
+            'ON-ACTIVATION': 'On-Activation',
+            'PRE-EXIT':      'Pre-Exit',
+            'ON-EXIT':       'On-Exit',
+            'PRE-COMMIT':    'Pre-Commit',
+            'POST-COMMIT':   'Post-Commit'}
 
-    self._in_trigger_lock = False
-    self._form = self
+        self._triggerFunctions = {
+            'setFocus': {
+                'function': self.triggerSetFocus,
+                'global'  : True},
+            'getAuthenticatedUser': {
+                'function': self.triggerGetAuthenticatedUser,
+                'global'  : True},
+            'setTitle': {
+                'function': self.triggerSetTitle,
+                'global'  : True},
+            'getCurrentBlockName': {
+                'function': self.triggerGetCurrentBlockName,
+                 'global' : True},
+            'setStatusText': {
+                'function':self.triggerSetStatusText,
+                'global': True},
+            'getParameter': {
+                'function': self.getParameter,
+                'global'  : True},
+            'setParameter': {
+                'function': self.triggerSetParameter,
+                'global'  : True},
+            'showMessage': {
+                'function': self.triggerShowMessageBox,
+                'global': True},
+            'messageBox': {
+                'function': self.triggerMessageBox,
+                'global': True},
+            'commit': {
+                'function': self.triggerCommit,
+                'global': True},
+            'rollback': {
+                'function': self.rollback,
+                'global': True},
+            'close': {
+                'function': self.triggerClose,
+                'global': True},
+            'beep': {
+                'function': self.triggerBeep,
+                'global': True},
+            'getFeature': {
+                'function': self.triggerGetFeature,
+                'global': True},
+            'setFeature': {
+                'function': self.triggerSetFeature,
+                'global': True},
+            'runForm': {
+                'function': self.triggerRunForm,
+                'global': True},
+            'runReport': {
+                'function': self.triggerRunReport,
+                'global': True},
+            'activateDialog': {
+                'function': self.triggerActivateDialog,
+                'global': True},
+            'activateTrigger': {
+                'function': self.fireTrigger,
+                'global': True},
+            'initQuery': {
+                'function': self.initQuery},
+        }
 
-  #---------------------------------------------------------------------------
-  # Called during phaseInit startup by GParser.
-  #---------------------------------------------------------------------------
-  def primaryInit(self):
-    """
-    Called automatically during phaseInit() startup of GParser.
-    """
-    # Initialize our events system
-    events.EventAware.__init__(self, self._instance.eventController)
+        self._features = {
+            'GUI:MENUBAR:SUPPRESS': False,
+            'GUI:TOOLBAR:SUPPRESS': False,
+            'GUI:STATUSBAR:SUPPRESS': False,
+        }
 
-    # Find the logic and layout controllers
-    for child in self._children:
-      if child._type == 'GFLogic':
-        self._logic = child
-      elif child._type == 'GFLayout':
-        self._layout = child
+        self._in_trigger_lock = False
+        self._form = self
 
-    self.initTriggerSystem()
-    ConnectionTriggerObj.addAllConnections(self._instance.connections, 
self._triggerNamespaceTree)
-    self._triggerns.update(self._triggerNamespaceTree._globalNamespace)
 
-    ## TODO: This ain't right!  Fix after 0.5.0
-    #self._triggerns['runForm'] = self.triggerRunForm
-    ## TODO
+    # -------------------------------------------------------------------------
+    # Phase 1 initialization
+    # -------------------------------------------------------------------------
 
+    def phase_1_init(self):
+        """
+        Called automatically during phaseInit() startup of GParser.
+        """
 
-  #---------------------------------------------------------------------------
-  # Secondary init-stuff that must happen after all our children have init'ed
-  #---------------------------------------------------------------------------
-  def secondaryInit(self):
-    """
-    Called automatically during phaseInit().
-    It must happen after all children have init'ed.
-    """
-    # create the first records
-    for key in self._datasourceDictionary.keys():
-      if not self._datasourceDictionary[key].hasMaster():
-        self._datasourceDictionary[key].createEmptyResultSet()
+        events.EventAware.__init__(self, self._instance.eventController)
 
-    # Set initial focus
-    self.findAndChangeFocus(self)
-    self.processTrigger('On-Startup')
+        # Find the logic and layout controllers
+        for child in self._children:
+            if child._type == 'GFLogic':
+                self._logic = child
+            elif child._type == 'GFLayout':
+                self._layout = child
 
+        self.initTriggerSystem()
+        ConnectionTriggerObj.addAllConnections(self._instance.connections,
+                self._triggerNamespaceTree)
+        self._triggerns.update(self._triggerNamespaceTree._globalNamespace)
 
-  #---------------------------------------------------------------------------
-  # Get a user parameter. If parameter not specified, pull default value
-  #---------------------------------------------------------------------------
-  def getParameter(self, parameter):
-    """
-    Gets a user parameter. If parameter is not specified, pulls default value.
-    @param parameter: case-insensitive name of parameter
-    @return: parameter value or None
-    """
 
-    # If _parameters are not yet set, fall back to the parameter dictionary of
-    # the GFInstance. This can only happen in ON-STARTUP triggers.
-    if not hasattr (self, '_parameters'):
-      self._parameters = self._instance._parameters
+    # -------------------------------------------------------------------------
+    # Phase 3 initialization
+    # -------------------------------------------------------------------------
 
-    try:
-      # _parameters is a CaselessDict, so the case of parameter doesn't matter
-      return self._parameters [parameter]
+    def phase_3_init(self):
+        """
+        Called automatically during phaseInit().  It must happen after all
+        children have init'ed.
+        """
+        # create the first records
+        for key in self._datasourceDictionary.keys():
+          if not self._datasourceDictionary[key].hasMaster():
+            self._datasourceDictionary[key].createEmptyResultSet()
 
-    except KeyError:
-      rv = None
-      pn = parameter.lower ()
+        # Set initial focus
+        self.findAndChangeFocus(self)
+        self.processTrigger('On-Startup')
 
-      for child in self._children:
-        if isinstance (child, GFParameter) and child._name == pn:
-          if hasattr (child, 'default'):
-            rv = child.default
-          else:
-            rv = None
-          self._parameters [pn] = rv
-          break
 
-    return rv
+    # =========================================================================
+    # Trigger functions
+    # =========================================================================
 
+    def getParameter(self, parameter):
+        """
+        Gets a user parameter. If parameter is not specified, pulls default
+        value.
 
-  #===========================================================================
-  # Focus functions
-  #===========================================================================
+        @param parameter: case-insensitive name of parameter
+        @return: parameter value or None
+        """
 
-  #---------------------------------------------------------------------------
-  # Runs findFocus and then runs changeFocus with that value.
-  #---------------------------------------------------------------------------
-  def findAndChangeFocus(self, object):
-    """
-    Change the focus to the first focusable element of the given object.
+        # If _parameters are not yet set, fall back to the parameter dictionary
+        # of the GFInstance.  This can only happen in ON-STARTUP triggers.
+        if not hasattr(self, '_parameters'):
+          self._parameters = self._instance._parameters
 
-    The object passed can be a page or a block (in which case the first entry
-    on that page/block will be focused) or an entry (in which case exactly this
-    entry will be focused).
+        try:
+            # _parameters is a CaselessDict, so the case of parameter doesn't
+            # matter.
+            return self._parameters[parameter]
 
-    The focus will be set on GF and on UI layer.
+        except KeyError:
+          rv = None
+          pn = parameter.lower()
 
-    @param: Object from the GF layer
-    """
-    entry = self.findFocus(object)
-    if entry:
-      # Set focus on GF layer
-      self.changeFocus(entry)
-      # Set focus on UI layer
-      self.dispatchEvent('gotoENTRY', object=entry, _form=self)
+          for child in self._children:
+              if isinstance(child, GFParameter) and child._name == pn:
+                  rv = getattr(child, 'default', None)
+                  self._parameters [pn] = rv
+                  break
 
+        return rv
 
-  #---------------------------------------------------------------------------
-  # Find the next focusable item given an item of type Page, Block, or Entry
-  # Only called by findAndChangeFocus
-  #---------------------------------------------------------------------------
-  def findFocus(self, object):
-    """
-    Finds the next focusable item of a page, a block or an entry.
-    @param: object (page, block or entry) to find next focus for.
-    @return: None or entry with next focus
-    """
+
+    # =========================================================================
+    # Focus functions
+    # =========================================================================
+
+    def findAndChangeFocus(self, object):
+        """
+        Change the focus to the first focusable element of the given object.
+
+        The object passed can be a page or a block (in which case the first
+        entry on that page/block will be focused) or an entry (in which case
+        exactly this entry will be focused).
+
+        The focus will be set on GF and on UI layer.
+
+        @param: Object from the GF layer
+        """
+
+        entry = self.findFocus(object)
+        if entry:
+            # Set focus on GF layer
+            self.changeFocus(entry)
+            # Set focus on UI layer
+            self.dispatchEvent('gotoENTRY', object=entry, _form=self)
+
+
+    # -------------------------------------------------------------------------
+    # Find the next focusable item starting at a given GFObject
+    # -------------------------------------------------------------------------
+
+    def findFocus(self, object):
+        """
+        Finds the next focusable item of a page, a block or an entry.
+
+        @param: object (page, block or entry) to find next focus for.
+        @return: None or entry with next focus
+        """
     
-    if object._type == 'GFField':
-      assert gDebug (5, "GFField was passed to 'findFocus'.")
-      try:
-        object = object._entryList[0]
-      except IndexError:
+        if object._type == 'GFField':
+            assert gDebug(5, "GFField was passed to 'findFocus'.")
+            try:
+                object = object._entryList[0]
+            except IndexError:
+                return None
+
+        if isinstance(object, GFTabStop):
+            if object.is_navigable(self.getCurrentMode()):
+                return object
+
+
+        elif isinstance(object, GFContainer):
+            for child in object.get_focus_order():
+                return self.findFocus(child)
+
+        else:
+            # If the object is neither a TabStop or a Container search for a
+            # container object and try to retrieve a focus object from it.  We
+            # are looking for the visual items first, and then fall back to the
+            # blocks.
+            container = ['GFPage', 'GFBox', 'GFBlock']
+            for item in container:
+                for child in object.findChildrenOfType (item, False, True):
+                    entry = self.findFocus (child)
+                    if entry:
+                        return entry
+
         return None
 
-    entry = None
 
-    mode = self.getCurrentMode()
+    # -------------------------------------------------------------------------
+    # Return the editing mode of the current record
+    # -------------------------------------------------------------------------
 
-    if isinstance(object, GFObj):
-      if object.is_navigable(mode):
-        return object
-      else:
-        if hasattr(object, 'get_focus_order'):
-          for child in object.get_focus_order():
-            entry = self.findFocus(child)
-            if entry:
-              return entry
-        #
-        # We're in trouble.  Scan all children for a
-        # focusable widget.  Will dump GFField objects
-        # stored in blocks into itself.
-        #
-        for child in object._children:
-          entry = self.findFocus(child)
-          if entry:
-            break
+    def getCurrentMode(self):
+        """
+        Returns the editing mode of the current record
+        @return: 'query', 'new' or 'edit'
+        """
+        if self._currentBlock:
+            if self._currentBlock.mode == 'query':
+                return 'query'
+            elif self._currentBlock.isEmpty():
+                return 'new'
+            else:
+                return 'edit'
+        else:
+            return 'new'
 
-    return entry
+    # -------------------------------------------------------------------------
+    # Changes to the requested entry object requested by an event source
+    # -------------------------------------------------------------------------
 
+    def changeFocus(self, widget, fireFocusTriggers=True):
+        """
+        Changes focus to the requested entry object.
+        @param widget: entry to put focus on
+        @param fireFocusTriggers: whether to fire focus-change trigger?
 
-  #---------------------------------------------------------------------------
-  # Returns the editing mode of the current record
-  #---------------------------------------------------------------------------
-  def getCurrentMode(self):
-    """
-    Returns the editing mode of the current record
-    @return: 'query', 'new' or 'edit'
-    """
-    if self._currentBlock:
-      if self._currentBlock.mode == 'query':
-        return 'query'
-      elif self._currentBlock.isEmpty():
-        return 'new'
-      else:
-        return 'edit'
-    else:
-      return 'new'
+        @raises MinimumLengthError: if the field of an entry specifies a
+          minimum length and the current value is too short
+        """
 
-  #---------------------------------------------------------------------------
-  # Changes to the requested entry object requested by an event source
-  #---------------------------------------------------------------------------
-  def changeFocus(self, widget, fireFocusTriggers=True):
-    """
-    Changes focus to the requested entry object.
-    @param widget: entry to put focus on
-    @param fireFocusTriggers: whether to fire focus-change trigger?
-    """
+        # cannot change focus to same entry
+        if widget == self._currentEntry:
+            assert gDebug(5, "Current entry did not change from %s" % widget)
+            return
 
-    message = None
+        assert gDebug(5, "Change focus: %s->%s" % (self._currentEntry, widget))
 
-    # cannot change focus to same entry
-    if widget == self._currentEntry:
-      assert gDebug (5, "Current entry did not change from %s" % widget)
-      return
+        message = None
+        try:
+            if self._currentEntry:
+                if self._currentEntry._type != 'GFButton':
+                    value = self._currentEntry.getValue()
+                    vstr  = "%s" % value
 
-    cen = self._currentEntry is not None and self._currentEntry.name or '-'
-    win = widget is not None and widget.name or '-'
-    assert gDebug (5, "Changing focus from %s (%s) to %s (%s)" % \
-               (self._currentEntry, cen, widget, win))
+                    minl = self._currentEntry._field.minLength
+                    if minl and value is not None and len (vstr):
+                        if len (vstr) < minl:
+                            raise MinimumLengthError (minl)
 
-    try:
-      if self._currentEntry:
+            fieldChange = widget != self._currentEntry
 
-        if self._currentEntry._type != 'GFButton':
-          val = self._currentEntry.getValue()
-          # Don't use something like str (val) since this fails for unicode
-          # values
-          strval = "%s" % val
+            # Determine wether the block should be changed.  Since buttons do
+            # have a block attribute now, we have to take care a bit.  Only set
+            # a blockChange if the widget has a valid block attribute.
+            newBlock = getattr(widget, '_block', None)
+            if newBlock is not None:
+                blockChange = self._currentBlock != newBlock
+            else:
+                blockChange = False
 
-          if self._currentEntry._field.minLength and val is not None and \
-              len (strval):
-            if len (strval) < self._currentEntry._field.minLength:
-              message = u_("Minimum required length %d") \
-                        % self._currentEntry._field.minLength
-              # Piggybacking off the triggers message box code
-              self.triggerShowMessageBox (message)
-              return
+            pageChange = widget._page != self._currentPage
 
-        event = events.Event ('endEDITMODE', _form = self)
-        self.dispatchEvent (event)
+            if fireFocusTriggers:
+                self.__focus_triggers('FocusOut', fieldChange, pageChange,
+                        blockChange)
 
-        if event.__error__:
-          return True
+            oldEntry = self._currentEntry
 
-      fieldChange = widget != self._currentEntry
+            self._currentEntry = widget
+            if newBlock is not None:
+                self._currentBlock = newBlock
 
-      # Determine wether the block should be changed.  Since buttons do have a
-      # block attribute now, we have to take care a bit.  Only set a
-      # blockChange if the widget has a valid block attribute.
-      newBlock = getattr(widget, '_block', None)
-      if newBlock is not None:
-          blockChange = self._currentBlock != newBlock
-      else:
-          blockChange = False
+            self._currentPage = self._currentEntry._page
 
-      pageChange = widget._page != self._currentPage
+            if pageChange:
+                self.dispatchEvent('gotoPAGE', self._currentPage, _form=self);
 
-      if fireFocusTriggers:
-        try:
-          if fieldChange:
-            self._currentEntry.processTrigger('Pre-FocusOut', 
ignoreAbort=False)
-            if hasattr(self._currentEntry,'_field'):
-              self._currentEntry._field.processTrigger('Pre-FocusOut', 
ignoreAbort=False)
-          if blockChange:
-            self._currentBlock.processTrigger('Pre-FocusOut', 
ignoreAbort=False)
-          if pageChange:
-            self._currentPage.processTrigger('Pre-FocusOut', ignoreAbort=False)
-            self._currentPage.processTrigger('Post-FocusOut', 
ignoreAbort=False)
-          if blockChange:
-            self._currentBlock.processTrigger('Post-FocusOut', 
ignoreAbort=False)
-          if fieldChange:
-            self._currentEntry.processTrigger('Post-FocusOut', 
ignoreAbort=False)
-            if hasattr(self._currentEntry,'_field'):
-              self._currentEntry._field.processTrigger('Post-FocusOut', 
ignoreAbort=False)
-        except AttributeError:
-          pass
+            if blockChange:
+                self.refreshDisplay(self._currentBlock)
 
-      oldEntry = self._currentEntry
+            assert gDebug(5, "Updating entries old: %s, new: %s" % \
+                    (oldEntry, self._currentEntry))
 
-      self._currentEntry = widget
-      if newBlock is not None:
-          self._currentBlock = newBlock
+            self.dispatchEvent('updateENTRY', oldEntry, _form=self)
+            self.dispatchEvent('updateENTRY', self._currentEntry, _form=self)
 
-      self._currentPage = self._currentEntry._page
+            if fireFocusTriggers:
+                self.__focus_triggers('FocusIn', fieldChange, pageChange,
+                        blockChange)
 
-      if pageChange:
-        self.dispatchEvent('gotoPAGE',self._currentPage, _form=self);
+                if blockChange or pageChange:
+                    self._instance.updateStatus (self)
 
-      if blockChange:
-          self.refreshDisplay(self._currentBlock)
+            assert gDebug(5, "calling refreshUIEvents ()")
+            self.refreshUIEvents()
+            assert gDebug(5, "CurrentEntry is %s" % self._currentEntry)
 
-      assert gDebug (5, "Updating entries old: %s, new: %s" % \
-                 (oldEntry, self._currentEntry))
+        except:
+            # TODO: this shouldn't be needed here
+            self.beginEditing ()
+            raise
 
-      self.dispatchEvent('updateENTRY', oldEntry, _form=self)
-      self.dispatchEvent('updateENTRY', self._currentEntry, _form=self)
+        return message
 
-      if fireFocusTriggers:
-        if pageChange:
-          self._currentPage.processTrigger('Pre-FocusIn', ignoreAbort=False)
-        if blockChange:
-          self._currentBlock.processTrigger('Pre-FocusIn', ignoreAbort=False)
-        if fieldChange:
-          self._currentEntry.processTrigger('Pre-FocusIn', ignoreAbort=False)
-          if hasattr(self._currentEntry,'_field'):
-            self._currentEntry._field.processTrigger('Pre-FocusIn', 
ignoreAbort=False)
-          if hasattr(self._currentEntry,'_field'):
-            self._currentEntry._field.processTrigger('Post-FocusIn', 
ignoreAbort=False)
-          self._currentEntry.processTrigger('Post-FocusIn', ignoreAbort=False)
-        if blockChange:
-          self._currentBlock.processTrigger('Post-FocusIn', ignoreAbort=False)
-        if pageChange:
-          self._currentPage.processTrigger('Post-FocusIn', ignoreAbort=False)
-        if blockChange or pageChange:
-          self._instance.updateStatus (self)
 
-      assert gDebug (5, "calling refreshUIEvents ()")
-      self.refreshUIEvents()
-      assert gDebug (5, "CurrentEntry is %s" % self._currentEntry)
+    # -------------------------------------------------------------------------
+    # Fire focus triggers
+    # -------------------------------------------------------------------------
 
-    except AbortRequest, t:
-      assert gDebug (5, "Trigger Error!")
-      message = _("Trigger Exception :\n") + t.message
+    def __focus_triggers (self, trigger, fieldChange, pageChange, blockChange):
 
-    return message
+        pre   = 'Pre-%s' % trigger
+        post  = 'Post-%s' % trigger
+        entry = self._currentEntry
+        field = getattr(self._currentEntry, '_field', None)
+        block = self._currentBlock
+        page  = self._currentPage
 
+        if fieldChange and entry:
+            entry.processTrigger(pre, ignoreAbort = False)
+            if field:
+                field.processTrigger(pre, ignoreAbort = False)
 
+        if blockChange and block:
+            block.processTrigger(pre, ignoreAbort = False)
+
+        if pageChange and page:
+            page.processTrigger(pre, ignoreAbort = False)
+            page.processTrigger(post, ignoreAbort = False)
+
+        if blockChange and block:
+            block.processTrigger(post, ignoreAbort = False)
+
+        if fieldChange and entry:
+            self._currentEntry.processTrigger(post, ignoreAbort = False)
+            if field:
+                field.processTrigger(post, ignoreAbort = False)
+
+
+
   #===========================================================================
   # Events
   #
   # Incoming Event handlers
   #===========================================================================
 
-  #---------------------------------------------------------------------------
-  # Create a new, empty record.
-  #---------------------------------------------------------------------------
-  def newRecord(self):
-    """
-    Creates a new, empty record.
-    """
-    if not self.readonly:
-      self._currentBlock.newRecord()
+    # -------------------------------------------------------------------------
+    # Create a new, empty record
+    # -------------------------------------------------------------------------
+    def newRecord(self):
+        """
+        Creates a new, empty record.
+        """
+        if not self.readonly:
+          self._currentBlock.newRecord()
 
 
-  # --------------------------------------------------------------------------
-  # Delete the current record.
-  # --------------------------------------------------------------------------
+    # -------------------------------------------------------------------------
+    # Delete the current record.
+    # -------------------------------------------------------------------------
 
-  def deleteRecord (self):
-    """
-    Deletes the actual record.
-    """
-    if not self.readonly:
-      self._currentBlock.deleteRecord()
-      self.refreshUIEvents()
+    def deleteRecord (self):
+        """
+        Deletes the actual record.
+        """
+        if not self.readonly:
+          self._currentBlock.deleteRecord()
+          self.refreshUIEvents()
 
 
-  # --------------------------------------------------------------------------
-  # Undelete the current record.
-  # --------------------------------------------------------------------------
+    # -------------------------------------------------------------------------
+    # Undelete the current record
+    # -------------------------------------------------------------------------
 
-  def undeleteRecord (self):
-    """
-    Undeletes the actual record.
-    """
-    if not self.readonly:
-      self._currentBlock.undeleteRecord()
-      self.refreshUIEvents()
+    def undeleteRecord (self):
+        """
+        Undeletes the actual record.
+        """
+        if not self.readonly:
+          self._currentBlock.undeleteRecord()
+          self.refreshUIEvents()
 
 
-  #---------------------------------------------------------------------------
-  # Check all blocks in the form whether they are saved (committed) or not.
-  #---------------------------------------------------------------------------
-  def isSaved(self):
-    """
-    Checks all block in the form whether they are saved (committed) or not.
-    @return: boolean, True if all the blocks are committed.
-    """
+    # -------------------------------------------------------------------------
+    # Check all blocks in the form whether they are saved (committed) or not.
+    # -------------------------------------------------------------------------
 
-    # Is the current entry changed?
-    # FIXME: should only cause the form to appear unsaved if the entry is bound
-    # to a field.
-    if (self._currentEntry._type != 'GFButton' and \
-        self._currentEntry._field._bound and \
-        self._currentEntry._displayHandler.isPending()):
-      return False
+    def isSaved(self):
+        """
+        Checks all block in the form whether they are saved (committed) or not.
+        @return: boolean, True if all the blocks are committed.
+        """
 
-    # Are there any not yet posted changes in any of the blocks?
-    for block in self._logic._blockList:
-      if block.isPending():
-        return False
+        # Is the current entry changed?
+        # FIXME: should only cause the form to appear unsaved if the entry is 
bound
+        # to a field.
+        if (self._currentEntry._type != 'GFButton' and \
+            self._currentEntry._field._bound and \
+            self._currentEntry._displayHandler.isPending()):
+          return False
 
-    # Does a connection have any pending (already posted but not yet committed)
-    # changes?
-    for connection in (self.__getConnections ()).values ():
-      if connection.isPending ():
-        return False
+        # Are there any not yet posted changes in any of the blocks?
+        for block in self._logic._blockList:
+          if block.isPending():
+            return False
 
-    return True
+        # Does a connection have any pending (already posted but not yet 
committed)
+        # changes?
+        for connection in (self.__getConnections ()).values ():
+          if connection.isPending ():
+            return False
 
+        return True
 
-  #---------------------------------------------------------------------------
-  # Enter the form into Query mode
-  #---------------------------------------------------------------------------
-  def initQuery(self):
-    """
-    Enters the form into Query mode.
-    @return: None if all went well, error message in case of error.
-    """
-    message = None
-    if self._currentBlock.mode != 'query':
 
-      # Auto-commit?
-      if self._currentBlock.autoCommit:
-        self.commit()
+    # -------------------------------------------------------------------------
+    # Enter the form into Query mode
+    # -------------------------------------------------------------------------
 
-      for block in self._logic._blockList:
-        if block.isPending():
-          message = _("Data not saved. Save changes or clear the form to "
-                      "proceed.")
-          return message
+    def initQuery(self):
+        """
+        Enters the form into Query mode.
+        @return: None if all went well, error message in case of error.
+        """
+        message = None
+        if self._currentBlock.mode != 'query':
 
-    for block in self._logic._blockList:
-      block.processRollback()
-      for entry in block._entryList:
-        if hasattr(entry, 'queryDefault'):
-          assert gDebug (5, "%s will be set to %s" % (entry.name, 
entry.queryDefault))
-          entry.setValue(entry.queryDefault)
+          # Auto-commit?
+          if self._currentBlock.autoCommit:
+            self.commit()
 
-    # If Enter-Query is hit once, enter query mode
-    # If Enter-Query is hit twice, bring back conditions from last query.
-    # If Enter-Query is hit thrice, cancel the query and go into normal mode.
+          for block in self._logic._blockList:
+            if block.isPending():
+              message = _("Data not saved. Save changes or clear the form to "
+                          "proceed.")
+              return message
 
-    self.dispatchEvent('beginENTERQUERY', _form=self)
-    #self._instance.dispatchEvent('beginENTERQUERY', _form=self)
+        for block in self._logic._blockList:
+          block.processRollback()
+          for entry in block._entryList:
+            if hasattr(entry, 'queryDefault'):
+              assert gDebug (5, "%s will be set to %s" % (entry.name, 
entry.queryDefault))
+              entry.setValue(entry.queryDefault)
 
-    for block in self._logic._blockList:
-      block.initQuery()
+        # If Enter-Query is hit once, enter query mode
+        # If Enter-Query is hit twice, bring back conditions from last query.
+        # If Enter-Query is hit thrice, cancel the query and go into normal 
mode.
 
-    self.triggerSetStatusText(_('Enter your query criteria.'))
-    return message
+        self.dispatchEvent('beginENTERQUERY', _form=self)
+        #self._instance.dispatchEvent('beginENTERQUERY', _form=self)
 
+        for block in self._logic._blockList:
+          block.initQuery()
 
-  #---------------------------------------------------------------------------
-  # Cancel Query mode
-  #---------------------------------------------------------------------------
-  def cancelQuery(self):
-    """
-    Cancels Query mode.
-    @return: None
-    """
-    self.dispatchEvent('endENTERQUERY', _form=self)
-    #self._instance.dispatchEvent('endENTERQUERY', _form=self)
-    message = None  #TODO: not used here and in return line /kilo/
-    for block in self._logic._blockList:
-      block.cancelQuery()
+        self.triggerSetStatusText(_('Enter your query criteria.'))
+        return message
 
-    self.triggerSetStatusText(_('Query canceled.'))
-    return message
 
+    # -------------------------------------------------------------------------
+    # Cancel Query mode
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Copy Query, ie bring back conditions from the last query
-  #---------------------------------------------------------------------------
-  def copyQuery(self):
-    """
-    Copies the Query, ie brings back conditions from the last query.
-    @return: None
-    """
-    if self._currentBlock.mode != 'query':
-      self.initQuery()
+    def cancelQuery(self):
+        """
+        Cancels Query mode.
+        @return: None
+        """
+        self.dispatchEvent('endENTERQUERY', _form=self)
+        #self._instance.dispatchEvent('endENTERQUERY', _form=self)
+        message = None  #TODO: not used here and in return line /kilo/
+        for block in self._logic._blockList:
+          block.cancelQuery()
 
-    self.dispatchEvent('endENTERQUERY', _form=self);
-    #self._instance.dispatchEvent('endENTERQUERY', _form=self);
-    message = None  #TODO: not used here and in return line /kilo/
-    for block in self._logic._blockList:
-      block.copyQuery()
+        self.triggerSetStatusText(_('Query canceled.'))
+        return message
 
-    return message
 
+    # -------------------------------------------------------------------------
+    # Copy Query, ie bring back conditions from the last query
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Run the query
-  #---------------------------------------------------------------------------
-  def executeQuery (self):
-    """
-    Runs the query.
-    @return: None if all went well, error message if there was an error
-    """
-    if self._currentBlock.mode != 'query':
-      return _("Form not in query mode")
+    def copyQuery(self):
+        """
+        Copies the Query, ie brings back conditions from the last query.
+        @return: None
+        """
+        if self._currentBlock.mode != 'query':
+          self.initQuery()
 
-    message = None
-    self.dispatchEvent ('endENTERQUERY', _form = self);
-    self.dispatchEvent ('beginWAIT', _form = self);
+        self.dispatchEvent('endENTERQUERY', _form=self);
+        #self._instance.dispatchEvent('endENTERQUERY', _form=self);
+        message = None  #TODO: not used here and in return line /kilo/
+        for block in self._logic._blockList:
+          block.copyQuery()
 
-    try:
-      try:
-        self._currentBlock.processQuery ()
+        return message
 
-      except DBError:
-        self.rollback (1)
-        message = u_("Database query error:\n%(exType)s\n%(exMessage)s") \
-            % {'exType'   : sys.exc_info ()[0],
-               'exMessage': sys.exc_info ()[1]}
 
-    finally:
-      self.dispatchEvent ('endWAIT', _form = self)
+    # -------------------------------------------------------------------------
+    # Run the query
+    # -------------------------------------------------------------------------
 
-    self.refreshDisplay (self._currentBlock)
-    if self._currentBlock.isEmpty ():
-      self.triggerSetStatusText (_('Query returned no results.'))
-    else:
-      self.triggerSetStatusText (_('Query successful.'))
+    def executeQuery (self):
+        """
+        Runs the query.
+        @return: None if all went well, error message if there was an error
+        """
+        if self._currentBlock.mode != 'query':
+          return _("Form not in query mode")
 
-    return message
+        message = None
+        self.dispatchEvent ('endENTERQUERY', _form = self);
+        self.dispatchEvent ('beginWAIT', _form = self);
 
+        try:
+          try:
+            self._currentBlock.processQuery ()
 
-  #---------------------------------------------------------------------------
-  # Commit all pending changes
-  #---------------------------------------------------------------------------
-  def commit(self):
-    """
-    Commits all pending changes.
-    @return: None if all went well, error message otherwise
-    """
+          except DBError:
+            self.rollback (1)
+            message = u_("Database query error:\n%(exType)s\n%(exMessage)s") \
+                % {'exType'   : sys.exc_info ()[0],
+                   'exMessage': sys.exc_info ()[1]}
 
-    assert gEnter (4)
+        finally:
+          self.dispatchEvent ('endWAIT', _form = self)
 
-    self.endEditing ()
-    if self.readonly:
-      return _('Form is readonly')
-    
-    message = None
-    newBlock = None                     # block to jump to after commit
-    self.dispatchEvent ('beginWAIT', _form = self)
+        self.refreshDisplay (self._currentBlock)
+        if self._currentBlock.isEmpty ():
+          self.triggerSetStatusText (_('Query returned no results.'))
+        else:
+          self.triggerSetStatusText (_('Query successful.'))
 
-    try:
-      # Save all current records, since they get lost in the Pre-Commit code
-      for block in self._logic._blockList:
-        block._precommitRecord = block._currentRecord
+        return message
 
-      # Form level pre-commit triggers
-      try:
-        self.processTrigger ('Pre-Commit', ignoreAbort = False)
 
-      except AbortRequest:
-        assert gDebug (5, "Trigger form Pre-Commit threw a AbortRequest!")
-        message = u_("Form trigger returned error")
+    # -------------------------------------------------------------------------
+    # Commit all pending changes
+    # -------------------------------------------------------------------------
 
+    def commit(self):
+        """
+        Commits all pending changes.
+        @return: None if all went well, error message otherwise
+        """
 
-      # Process the commit on all blocks
-      for block in self._logic._blockList:
-        assert gDebug (5, "Saving %s" % block.name)
+        assert gEnter (4)
+
+        self.endEditing ()
+        if self.readonly:
+          return _('Form is readonly')
+        
+        message = None
+        newBlock = None                     # block to jump to after commit
+        self.dispatchEvent ('beginWAIT', _form = self)
+
         try:
-          block.processCommit ()
+          # Save all current records, since they get lost in the Pre-Commit 
code
+          for block in self._logic._blockList:
+            block._precommitRecord = block._currentRecord
 
-        except AbortRequest:
-          assert gDebug (5, "Trigger block Pre-Commit threw a AbortRequest!")
-          message = u_("Block trigger returned error")
-          # jump to offending block
-          newBlock = block
-        except:
-          # jump to offending block
-          newBlock = block
-          raise
+          # Form level pre-commit triggers
+          try:
+            self.processTrigger ('Pre-Commit', ignoreAbort = False)
 
-      try:
-        # Now do the real commit () on the backend connections (only once per
-        # connection, if multiple blocks are sharing the same connection)
-        for conn in self.__getConnections ().values ():
-          conn.commit ()
+          except AbortRequest:
+            assert gDebug (5, "Trigger form Pre-Commit threw a AbortRequest!")
+            message = u_("Form trigger returned error")
 
-      except:
-        # Make sure the block is in consistent state again; this has to be
-        # done in any case if the processCommit was successful, even if the
-        # connection commit failed!
-        for block in self._logic._blockList:            
-          block.finalizeCommit (False)
-        raise
 
-      for block in self._logic._blockList:            
-        block.finalizeCommit (True)
+          # Process the commit on all blocks
+          for block in self._logic._blockList:
+            assert gDebug (5, "Saving %s" % block.name)
+            try:
+              block.processCommit ()
 
-      # Execute Post-Commit-Trigger for each block
-      for block in self._logic._blockList:
-        block.processTrigger ('Post-Commit')
+            except AbortRequest:
+              assert gDebug (5, "Trigger block Pre-Commit threw a 
AbortRequest!")
+              message = u_("Block trigger returned error")
+              # jump to offending block
+              newBlock = block
+            except:
+              # jump to offending block
+              newBlock = block
+              raise
 
-      for block in self._logic._blockList:
-        if block.autoClear:
-          block.processClear ()
+          try:
+            # Now do the real commit () on the backend connections (only once 
per
+            # connection, if multiple blocks are sharing the same connection)
+            for conn in self.__getConnections ().values ():
+              conn.commit ()
 
-      self.dispatchEvent ('cannotCOMMIT')
-      self.dispatchEvent ('cannotROLLBACK')
+          except:
+            # Make sure the block is in consistent state again; this has to be
+            # done in any case if the processCommit was successful, even if the
+            # connection commit failed!
+            for block in self._logic._blockList:            
+              block.finalizeCommit (False)
+            raise
 
-      # Execute Post-Commit-Trigger for the form
-      self.processTrigger ('Post-Commit')
+          for block in self._logic._blockList:            
+            block.finalizeCommit (True)
 
-    finally:
-      # Make sure the current block still has the focus, even if an exception
-      # occured during commit or in a trigger
-      if newBlock is not None and newBlock != self._currentBlock:
-        self.findAndChangeFocus (newBlock)
-      self.dispatchEvent ('endWAIT', _form = self)
+          # Execute Post-Commit-Trigger for each block
+          for block in self._logic._blockList:
+            block.processTrigger ('Post-Commit')
 
-    assert gLeave (4)
+          for block in self._logic._blockList:
+            if block.autoClear:
+              block.processClear ()
 
-    return message
+          self.dispatchEvent ('cannotCOMMIT')
+          self.dispatchEvent ('cannotROLLBACK')
 
+          # Execute Post-Commit-Trigger for the form
+          self.processTrigger ('Post-Commit')
 
-  #---------------------------------------------------------------------------
-  # Rolls back any uncommitted transatcion
-  #---------------------------------------------------------------------------
-  def rollback (self, recover = False):
-    """
-    Rolls back any uncommitted transaction.
-    @return: None
-    """
-    self.endEditing()
+        finally:
+          # Make sure the current block still has the focus, even if an 
exception
+          # occured during commit or in a trigger
+          if newBlock is not None and newBlock != self._currentBlock:
+            self.findAndChangeFocus (newBlock)
+          self.dispatchEvent ('endWAIT', _form = self)
 
-    # Call rollback only once per connection (if multiple blocks are sharing
-    # the same connection)
-    for (cName, connection) in self.__getConnections ().items ():
-      connection.rollback ()
+        assert gLeave (4)
 
-    for block in self._logic._blockList:
-      block.processRollback (recover, backendRollback = False)
+        return message
 
-    self.refreshDisplay (self)
-    self._currentBlock.jumpRecord(self._currentBlock._currentRecord)
-    self.dispatchEvent ('cannotCOMMIT')
-    self.dispatchEvent ('cannotROLLBACK')
 
+    # -------------------------------------------------------------------------
+    # Rolls back any uncommitted transatcion
+    # -------------------------------------------------------------------------
 
-  # ---------------------------------------------------------------------------
-  # Get all connections used by the form
-  # ---------------------------------------------------------------------------
+    def rollback (self, recover = False):
+        """
+        Rolls back any uncommitted transaction.
+        @return: None
+        """
+        self.endEditing()
 
-  def __getConnections (self):
-    """
-    This function creates a dictionary of all connections referenced by the 
form,
-    where the connection-name is the key and the connection instance is
-    the value.
+        # Call rollback only once per connection (if multiple blocks are 
sharing
+        # the same connection)
+        for (cName, connection) in self.__getConnections ().items ():
+          connection.rollback ()
 
-    @return: dictionary with all connections used by the form
-    """
+        for block in self._logic._blockList:
+          block.processRollback (recover, backendRollback = False)
 
-    result = {}
-    for dLink in self._datasourceDictionary.values():
-      try:
-        if dLink._connection is not None:
-          result [dLink.connection] = dLink._connection
-      except AttributeError:
-        pass
+        self.refreshDisplay (self)
+        self._currentBlock.jumpRecord(self._currentBlock._currentRecord)
+        self.dispatchEvent ('cannotCOMMIT')
+        self.dispatchEvent ('cannotROLLBACK')
+
+
+    # -------------------------------------------------------------------------
+    # Get all connections used by the form
+    # -------------------------------------------------------------------------
+
+    def __getConnections (self):
+        """
+        This function creates a dictionary of all connections referenced by the
+        form, where the connection-name is the key and the connection instance
+        is the value.
+
+        @return: dictionary with all connections used by the form
+        """
+
+        result = {}
+        for dLink in self._datasourceDictionary.values():
+          try:
+            if dLink._connection is not None:
+              result [dLink.connection] = dLink._connection
+          except AttributeError:
+            pass
+            
         
-    
-    return result
+        return result
 
 
-  #---------------------------------------------------------------------------
-  # Launch a trigger
-  #---------------------------------------------------------------------------
-  def fireTrigger(self, triggerName):
-    """
-    Launches a trigger.
-    @param triggerName: name of  the trigger to be launched.
-    @return: None
-    """
-    self._triggerDictionary[triggerName](self)
+    # -------------------------------------------------------------------------
+    # Launch a trigger
+    # -------------------------------------------------------------------------
 
+    def fireTrigger(self, triggerName):
+        """
+        Launches a trigger.
+        @param triggerName: name of  the trigger to be launched.
+        @return: None
+        """
+        self._triggerDictionary[triggerName](self)
 
-  #---------------------------------------------------------------------------
-  # Updates every UI entry of a field.
-  #---------------------------------------------------------------------------
-  def updateUIEntry(self, field):
-    """
-    Updates every UI entry of a field.
-    @param field: the field object whose ui is to be refreshed
-    @return: None
-    """
-    for entry in field._entryList:
-      self.dispatchEvent('updateENTRY', entry, _form=self)
-      #self._instance.dispatchEvent('updateENTRY',entry, _form=self)
 
+    # -------------------------------------------------------------------------
+    # Updates every UI entry of a field.
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Called whenever an event source has requested that the
-  # focus change to the next data entry object
-  #---------------------------------------------------------------------------
-  def nextEntry(self, reverse=False, first=False, onlyInBlock=False):
-    """
-    Called whenever an event source has requested that the focus change
-    to the next data entry object.
-    @param reverse: boolean, step focus in reverse direction?
-    @param first: boolean, change focus to the first entry in the block?
-    @param onlyInBlock: boolean, can jump out of block to next block?
-    @return: None
-    """
-    currentBlock = self._currentBlock
-    mode = self.getCurrentMode()
+    def updateUIEntry(self, field):
+        """
+        Updates every UI entry of a field.
+        @param field: the field object whose ui is to be refreshed
+        @return: None
+        """
+        for entry in field._entryList:
+          self.dispatchEvent('updateENTRY', entry, _form=self)
+          #self._instance.dispatchEvent('updateENTRY',entry, _form=self)
 
-    if currentBlock.transparent and not ( \
-          onlyInBlock or \
-          currentBlock.autoNextRecord and not ( \
-              currentBlock.isEmpty() or \
-              (not reverse and currentBlock.isLastRecord() and \
-                   not (currentBlock.autoCreate and \
-                        currentBlock.editable in ('Y', 'new')) or \
-              (reverse and currentBlock.isFirstRecord()) \
-          ))):
-      source = self._currentEntry._page.get_focus_order()
-      stayInBlock = False
-    else:
-      source = currentBlock.get_focus_order()
-      stayInBlock = True
 
-    # If we want the previous entry, then reverse the focusorder we're using
-    if reverse:
-      source.reverse()
+    # -------------------------------------------------------------------------
+    # Called whenever an event source has requested that the
+    # focus change to the next data entry object
+    # -------------------------------------------------------------------------
 
-    nextEntry = None
-    firstEntry = None
-    keepNext = False
+    def nextEntry(self, reverse=False, first=False, onlyInBlock=False):
+        """
+        Called whenever an event source has requested that the focus change
+        to the next data entry object.
+        @param reverse: boolean, step focus in reverse direction?
+        @param first: boolean, change focus to the first entry in the block?
+        @param onlyInBlock: boolean, can jump out of block to next block?
+        @return: None
+        """
+        currentBlock = self._currentBlock
+        mode = self.getCurrentMode()
 
-    for object in source:
+        if currentBlock.transparent and not ( \
+              onlyInBlock or \
+              currentBlock.autoNextRecord and not ( \
+                  currentBlock.isEmpty() or \
+                  (not reverse and currentBlock.isLastRecord() and \
+                       not (currentBlock.autoCreate and \
+                            currentBlock.editable in ('Y', 'new')) or \
+                  (reverse and currentBlock.isFirstRecord()) \
+              ))):
+          source = self._currentEntry._page.get_focus_order()
+          stayInBlock = False
+        else:
+          source = currentBlock.get_focus_order()
+          stayInBlock = True
 
-      if object.is_navigable(mode):
-        if stayInBlock and \
-           (currentBlock.name != object.block):
-          continue
-        # If we only wanted the first navigable field in the block, then return
-        if first:
-          nextEntry = object
-          break
+        # If we want the previous entry, then reverse the focusorder we're 
using
+        if reverse:
+          source.reverse()
 
-        # Put the first field as the next to rollover
-        if nextEntry == None:
-          nextEntry = object
-          firstEntry = object
+        nextEntry = None
+        firstEntry = None
+        keepNext = False
 
-        # If we're at the current focused entry,
-        # then the next entry will be what we want
-        if object == self._currentEntry:
-          keepNext = True
+        for object in source:
 
-        # If we've already passed the current entry
-        # Then this is the entry to return
-        elif keepNext:
-          nextEntry = object
-          break
+          if object.is_navigable(mode):
+            if stayInBlock and \
+               (currentBlock.name != object.block):
+              continue
+            # If we only wanted the first navigable field in the block, then 
return
+            if first:
+              nextEntry = object
+              break
 
-    # If we've cycled back around to the first entry, then do special checks
-    if nextEntry == firstEntry:
+            # Put the first field as the next to rollover
+            if nextEntry == None:
+              nextEntry = object
+              firstEntry = object
 
-      # If we should navigate to the next record, do it...
-      if reverse and not currentBlock.isFirstRecord():
-        currentBlock.prevRecord()
-        self.changeFocus(nextEntry)
-      elif not reverse and \
-         currentBlock.autoNextRecord and \
-         not currentBlock.isEmpty() and \
-         not (not currentBlock.autoCreate and \
-              currentBlock.isLastRecord()):
-           currentBlock.nextRecord()
+            # If we're at the current focused entry,
+            # then the next entry will be what we want
+            if object == self._currentEntry:
+              keepNext = True
 
-           # If new record is empty, then the
-           # nextEntry logic has been taken care of...
-           if currentBlock.isEmpty():
-             return
-           else:
-             self.changeFocus(nextEntry)
+            # If we've already passed the current entry
+            # Then this is the entry to return
+            elif keepNext:
+              nextEntry = object
+              break
 
-      # Otherwise, are we transparent? If so, go to next block/page
-      elif currentBlock.transparent and \
-         self._currentPage.transparent:
+        # If we've cycled back around to the first entry, then do special 
checks
+        if nextEntry == firstEntry:
 
-        # Jump to the next/(previous) page if block is page as transparent
-        pages =  self._layout._pageList
-        i = pages.index(self._currentPage)
+          # If we should navigate to the next record, do it...
+          if reverse and not currentBlock.isFirstRecord():
+            currentBlock.prevRecord()
+            self.changeFocus(nextEntry)
+          elif not reverse and \
+             currentBlock.autoNextRecord and \
+             not currentBlock.isEmpty() and \
+             not (not currentBlock.autoCreate and \
+                  currentBlock.isLastRecord()):
+               currentBlock.nextRecord()
 
-        if reverse:
-          try:
-            dest = self._layout._pageList[i - 1]
-          except IndexError:
-            dest = self._layout._pageList[-1]
-          # TODO: this fails if last entry is not navigable
-          self.findAndChangeFocus(dest._entryList[-1])
-        else:
-          try:
-            dest = self._layout._pageList[i + 1]
-          except IndexError:
-            dest = self._layout._pageList[0]
-          self.findAndChangeFocus(dest)
-      else:
-        self.changeFocus(nextEntry)
+               # If new record is empty, then the
+               # nextEntry logic has been taken care of...
+               if currentBlock.isEmpty():
+                 return
+               else:
+                 self.changeFocus(nextEntry)
 
-    else:
-      self.changeFocus(nextEntry)
+          # Otherwise, are we transparent? If so, go to next block/page
+          elif currentBlock.transparent and \
+             self._currentPage.transparent:
 
+            # Jump to the next/(previous) page if block is page as transparent
+            pages =  self._layout._pageList
+            i = pages.index(self._currentPage)
 
-  #---------------------------------------------------------------------------
-  # Called whenever an event source has requested that the
-  # focus change to the previous data entry object
-  #---------------------------------------------------------------------------
-  def previousEntry(self):
-    """
-    Called whenever an event source has requested that the focus change
-    to the previous data entry object.
-    @return: None
-    """
-    return self.nextEntry(reverse=True)
+            if reverse:
+              try:
+                dest = self._layout._pageList[i - 1]
+              except IndexError:
+                dest = self._layout._pageList[-1]
+              # TODO: this fails if last entry is not navigable
+              self.findAndChangeFocus(dest._entryList[-1])
+            else:
+              try:
+                dest = self._layout._pageList[i + 1]
+              except IndexError:
+                dest = self._layout._pageList[0]
+              self.findAndChangeFocus(dest)
+          else:
+            self.changeFocus(nextEntry)
 
+        else:
+          self.changeFocus(nextEntry)
 
-  #---------------------------------------------------------------------------
-  # Refreshes all the UI fields to match the virtual form's fields
-  #---------------------------------------------------------------------------
-  def refreshDisplay(self, block):
-    """
-    Refreshes all the UI fields to match the virtual form's fields.
-    @param block: block object containing fields to refresh
-    @return: None
-    """
-    block.walk(self.__refreshDisplay)
-    self.refreshUIEvents()
 
+    # -------------------------------------------------------------------------
+    # Called whenever an event source has requested that the
+    # focus change to the previous data entry object
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Refresh a given data entry object's UI
-  #---------------------------------------------------------------------------
-  def __refreshDisplay(self, object):
-    if object._type in ('GFEntry', "GFImage"):
-      self.dispatchEvent('updateENTRY',object, _form=self)
+    def previousEntry(self):
+        """
+        Called whenever an event source has requested that the focus change
+        to the previous data entry object.
+        @return: None
+        """
+        return self.nextEntry(reverse=True)
 
 
-  #---------------------------------------------------------------------------
-  # Signal the UI Drivers of navigation button relevance
-  #---------------------------------------------------------------------------
-  def refreshUIEvents(self):
-    """
-    Signals the UI drivers of navigation button relevance.
-    @return: None
-    """
-    block = self._currentBlock
-    if not block:
-      assert gDebug(5,'No current block - cannot refresh UI')
-      return
+    # -------------------------------------------------------------------------
+    # Refreshes all the UI fields to match the virtual form's fields
+    # -------------------------------------------------------------------------
 
-    dispatchEvent = self.dispatchEvent
-    if block.mode == 'query':
-      dispatchEvent('canCANCELQUERY')
-      dispatchEvent('canEXECQUERY')
-      dispatchEvent('cannotENTERQUERY')
-      dispatchEvent('cannotPREVRECORD')
-      dispatchEvent('cannotFIRSTRECORD')
-      dispatchEvent('cannotNEXTRECORD')
-      dispatchEvent('cannotLASTRECORD')
-      dispatchEvent('cannotCOMMIT')
-      dispatchEvent('cannotROLLBACK')
-      dispatchEvent('cannotJUMPPROMPT')
-      dispatchEvent('cannotNEWRECORD')
-      dispatchEvent('cannotMARKFORDELETE')
-    else:
-      dispatchEvent('canENTERQUERY')
-      dispatchEvent('cannotCANCELQUERY')
-      dispatchEvent('cannotEXECQUERY')
+    def refreshDisplay(self, block):
+        """
+        Refreshes all the UI fields to match the virtual form's fields.
+        @param block: block object containing fields to refresh
+        @return: None
+        """
+        block.walk(self.__refreshDisplay)
+        self.refreshUIEvents()
 
-      if not self.isSaved():
-        dispatchEvent('canCOMMIT')
-      else:
-        dispatchEvent('cannotCOMMIT')
 
-      dispatchEvent('canROLLBACK')
-      dispatchEvent('canJUMPPROMPT')
-      dispatchEvent('canMARKFORDELETE')
+    # -------------------------------------------------------------------------
+    # Refresh a given data entry object's UI
+    # -------------------------------------------------------------------------
 
-      if block._resultSet.isFirstRecord():
-        dispatchEvent('cannotPREVRECORD')
-        dispatchEvent('cannotFIRSTRECORD')
-      else:
-        dispatchEvent('canPREVRECORD')
-        dispatchEvent('canFIRSTRECORD')
+    def __refreshDisplay(self, object):
+        if object._type in ('GFEntry', "GFImage"):
+          self.dispatchEvent('updateENTRY',object, _form=self)
 
-      if block._resultSet.isLastRecord():
-        if block._resultSet.current.isEmpty():
+
+    # -------------------------------------------------------------------------
+    # Signal the UI Drivers of navigation button relevance
+    # -------------------------------------------------------------------------
+
+    def refreshUIEvents(self):
+        """
+        Signals the UI drivers of navigation button relevance.
+        @return: None
+        """
+        block = self._currentBlock
+        if not block:
+          assert gDebug(5,'No current block - cannot refresh UI')
+          return
+
+        dispatchEvent = self.dispatchEvent
+        if block.mode == 'query':
+          dispatchEvent('canCANCELQUERY')
+          dispatchEvent('canEXECQUERY')
+          dispatchEvent('cannotENTERQUERY')
+          dispatchEvent('cannotPREVRECORD')
+          dispatchEvent('cannotFIRSTRECORD')
           dispatchEvent('cannotNEXTRECORD')
+          dispatchEvent('cannotLASTRECORD')
+          dispatchEvent('cannotCOMMIT')
+          dispatchEvent('cannotROLLBACK')
+          dispatchEvent('cannotJUMPPROMPT')
+          dispatchEvent('cannotNEWRECORD')
+          dispatchEvent('cannotMARKFORDELETE')
         else:
-          dispatchEvent('canNEXTRECORD')
-        dispatchEvent('cannotLASTRECORD')
-      else:
-        dispatchEvent('canNEXTRECORD')
-        dispatchEvent('canLASTRECORD')
-        dispatchEvent('canNEWRECORD')
+          dispatchEvent('canENTERQUERY')
+          dispatchEvent('cannotCANCELQUERY')
+          dispatchEvent('cannotEXECQUERY')
 
-      if block._resultSet.current.isEmpty():
-        dispatchEvent('cannotNEWRECORD')
-      else:
-        dispatchEvent('canNEWRECORD')
+          if not self.isSaved():
+            dispatchEvent('canCOMMIT')
+          else:
+            dispatchEvent('cannotCOMMIT')
 
-      if block._resultSet.current.isDeleted () \
-          or block._resultSet.current.isVoid ():
-        dispatchEvent('cannotMARKFORDELETE')
-        dispatchEvent('canUNDELETE')
-        dispatchEvent('beginMARKFORDELETE')
-      else:
-        dispatchEvent('endMARKFORDELETE')
-        dispatchEvent('canMARKFORDELETE')
-        dispatchEvent('cannotUNDELETE')
+          dispatchEvent('canROLLBACK')
+          dispatchEvent('canJUMPPROMPT')
+          dispatchEvent('canMARKFORDELETE')
 
+          if block._resultSet.isFirstRecord():
+            dispatchEvent('cannotPREVRECORD')
+            dispatchEvent('cannotFIRSTRECORD')
+          else:
+            dispatchEvent('canPREVRECORD')
+            dispatchEvent('canFIRSTRECORD')
 
-  #---------------------------------------------------------------------------
-  # Called whenever an event source has requested that the
-  # focus change to the next data entry block
-  #---------------------------------------------------------------------------
-  def nextBlock(self):
-    """
-    Change focus to the next data entry block.
-    @return: None
-    """
-    try:
-      nextBlock = 
self._logic._blockList[self._logic._blockList.index(self._currentBlock) + 1]
-    except IndexError:
-      nextBlock = self._logic._blockList[0]
-    self.findAndChangeFocus(nextBlock)
+          if block._resultSet.isLastRecord():
+            if block._resultSet.current.isEmpty():
+              dispatchEvent('cannotNEXTRECORD')
+            else:
+              dispatchEvent('canNEXTRECORD')
+            dispatchEvent('cannotLASTRECORD')
+          else:
+            dispatchEvent('canNEXTRECORD')
+            dispatchEvent('canLASTRECORD')
+            dispatchEvent('canNEWRECORD')
 
+          if block._resultSet.current.isEmpty():
+            dispatchEvent('cannotNEWRECORD')
+          else:
+            dispatchEvent('canNEWRECORD')
 
-  #---------------------------------------------------------------------------
-  # Convenience routine to find the previous block
-  #---------------------------------------------------------------------------
-  def findPreviousBlock(self):
-    """
-    Finds the previous block.
-    @return: the block found
-    """
-    try:
-      return 
self._logic._blockList[self._logic._blockList.index(self._currentBlock) - 1]
-    except IndexError:
-      return self._logic._blockList[-1]
+          if block._resultSet.current.isDeleted () \
+              or block._resultSet.current.isVoid ():
+            dispatchEvent('cannotMARKFORDELETE')
+            dispatchEvent('canUNDELETE')
+            dispatchEvent('beginMARKFORDELETE')
+          else:
+            dispatchEvent('endMARKFORDELETE')
+            dispatchEvent('canMARKFORDELETE')
+            dispatchEvent('cannotUNDELETE')
 
 
-  #---------------------------------------------------------------------------
-  # Called whenever an event source has requested that the
-  # focus change to the previous data entry block
-  #---------------------------------------------------------------------------
-  def previousBlock(self):
-    """
-    Change focus to the previous data entry block.
-    @return: None
-    """
-    self.findAndChangeFocus(self.findPreviousBlock())
+    # -------------------------------------------------------------------------
+    # Called whenever an event source has requested that the
+    # focus change to the next data entry block
+    # -------------------------------------------------------------------------
 
+    def nextBlock(self):
+        """
+        Change focus to the next data entry block.
+        @return: None
+        """
+        try:
+          nextBlock = 
self._logic._blockList[self._logic._blockList.index(self._currentBlock) + 1]
+        except IndexError:
+          nextBlock = self._logic._blockList[0]
+        self.findAndChangeFocus(nextBlock)
 
-  #---------------------------------------------------------------------------
-  # Signal to the current Entry to stop editing
-  # mode and save it's value to the virtual form
-  #---------------------------------------------------------------------------
-  def endEditing(self):
-    """
-    Signals the current entry to stop editing mode and
-    save it's value to the virtual form.
-    @return: Boolean, True if succeeded, False if failed.
-    """
-    event = events.Event('endEDITMODE', None, _form=self)
-    self.dispatchEvent(event)
-    return not event.__error__
 
+    # -------------------------------------------------------------------------
+    # Convenience routine to find the previous block
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Step to previous record in block.
-  #---------------------------------------------------------------------------
-  def prevRecord(self):
-    """
-    Steps to the previous record in the current block.
-    @return: None
-    """
-    if self._currentBlock.mode == 'query':
-      self.triggerSetStatusText(_('You cannot do that in query mode.'))
-      return
-    self._currentBlock.prevRecord()
+    def findPreviousBlock(self):
+        """
+        Finds the previous block.
+        @return: the block found
+        """
+        try:
+          return 
self._logic._blockList[self._logic._blockList.index(self._currentBlock) - 1]
+        except IndexError:
+          return self._logic._blockList[-1]
 
 
-  #---------------------------------------------------------------------------
-  # Jump to first record in block.
-  #---------------------------------------------------------------------------
-  def firstRecord(self):
-    """
-    Jumps to the first record in the current block.
-    @return: None
-    """
-    if self._currentBlock.mode == 'query':
-      self.triggerSetStatusText(_('You cannot do that in query mode.'))
-      return
-    self._currentBlock.firstRecord()
+    # -------------------------------------------------------------------------
+    # Called whenever an event source has requested that the
+    # focus change to the previous data entry block
+    # -------------------------------------------------------------------------
 
+    def previousBlock(self):
+        """
+        Change focus to the previous data entry block.
+        @return: None
+        """
+        self.findAndChangeFocus(self.findPreviousBlock())
 
-  #---------------------------------------------------------------------------
-  # Jump to last record in block.
-  #---------------------------------------------------------------------------
-  def lastRecord(self):
-    """
-    Jumps to the last record in the current block.
-    @return: None
-    """
-    if self._currentBlock.mode == 'query':
-      self.triggerSetStatusText(_('You cannot do that in query mode.'))
-      return
-    self._currentBlock.lastRecord()
 
+    # -------------------------------------------------------------------------
+    # Signal to the current Entry to stop editing
+    # mode and save it's value to the virtual form
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Step to next record in block.
-  #---------------------------------------------------------------------------
-  def nextRecord(self):
-    """
-    Steps to the next record in the current block.
-    @return: None
-    """
-    if self._currentBlock.mode == 'query':
-      self.triggerSetStatusText(_('You cannot do that in query mode.'))
-      return
-    self._currentBlock.nextRecord()
+    def endEditing(self):
+        """
+        Signals the current entry to stop editing mode and
+        save it's value to the virtual form.
+        @return: Boolean, True if succeeded, False if failed.
+        """
+        event = events.Event('endEDITMODE', None, _form=self)
+        self.dispatchEvent(event)
+        return not event.__error__
 
+    # -------------------------------------------------------------------------
+    # Start editing mode of the current entry
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Jumpt to a given record in block.
-  #---------------------------------------------------------------------------
-  def jumpRecord(self, count):
-    """
-    Jumps to a given record in the current block.
-    @param count: ordinal of the record
-    @return: None
-    """
-    if self._currentBlock.mode == 'query':
-      self.triggerSetStatusText(_('You cannot do that in query mode.'))
-      return
-    self._currentBlock.jumpRecord(count)
+    def beginEditing(self):
+        event = events.Event('beginEDITMODE', None, _form = self)
+        self.dispatchEvent(event)
 
 
-  #---------------------------------------------------------------------------
-  # Toggles insert mode
-  #---------------------------------------------------------------------------
-  def toggleInsertMode(self):
-    """
-    Toggles insert mode.
-    @return: None
-    """
-    self._insertMode = not self._insertMode
 
+    # -------------------------------------------------------------------------
+    # Step to previous record in block
+    # -------------------------------------------------------------------------
 
+    def prevRecord(self):
+        """
+        Steps to the previous record in the current block.
+        @return: None
+        """
+        if self._currentBlock.mode == 'query':
+          self.triggerSetStatusText(_('You cannot do that in query mode.'))
+          return
+        self._currentBlock.prevRecord()
+
+
+    # -------------------------------------------------------------------------
+    # Jump to first record in block.
+    # -------------------------------------------------------------------------
+
+    def firstRecord(self):
+        """
+        Jumps to the first record in the current block.
+        @return: None
+        """
+        if self._currentBlock.mode == 'query':
+          self.triggerSetStatusText(_('You cannot do that in query mode.'))
+          return
+        self._currentBlock.firstRecord()
+
+
+    # -------------------------------------------------------------------------
+    # Jump to last record in block.
+    # -------------------------------------------------------------------------
+
+    def lastRecord(self):
+        """
+        Jumps to the last record in the current block.
+        @return: None
+        """
+        if self._currentBlock.mode == 'query':
+          self.triggerSetStatusText(_('You cannot do that in query mode.'))
+          return
+        self._currentBlock.lastRecord()
+
+
+    # -------------------------------------------------------------------------
+    # Step to next record in block.
+    # -------------------------------------------------------------------------
+
+    def nextRecord(self):
+        """
+        Steps to the next record in the current block.
+        @return: None
+        """
+        if self._currentBlock.mode == 'query':
+          self.triggerSetStatusText(_('You cannot do that in query mode.'))
+          return
+        self._currentBlock.nextRecord()
+
+
+    # -------------------------------------------------------------------------
+    # Jump to a given record in block.
+    # -------------------------------------------------------------------------
+
+    def jumpRecord(self, count):
+        """
+        Jumps to a given record in the current block.
+        @param count: ordinal of the record
+        @return: None
+        """
+        if self._currentBlock.mode == 'query':
+          self.triggerSetStatusText(_('You cannot do that in query mode.'))
+          return
+        self._currentBlock.jumpRecord(count)
+
+
+    # -------------------------------------------------------------------------
+    # Toggles insert mode
+    # -------------------------------------------------------------------------
+
+    def toggleInsertMode(self):
+        """
+        Toggles insert mode.
+        @return: None
+        """
+        self._insertMode = not self._insertMode
+
+
   #===========================================================================
   # Trigger functions
   #
@@ -1208,313 +1227,254 @@
   # functions exposed in the trigger namespace.
   #===========================================================================
 
-  #---------------------------------------------------------------------------
-  # trigger commits
-  #---------------------------------------------------------------------------
-  def triggerCommit(self):
-    """
-    Causes the form to commit
-    """  
-    event = events.Event('requestCOMMIT',_form=self)
-    self._instance.executeCommit(event)
-  
-  #---------------------------------------------------------------------------
-  # trigger beep
-  #---------------------------------------------------------------------------
-  def triggerBeep(self):
-    """
-    Tells the UI to beep (if possible)
-    
-    @return: None
-    """
-    self.dispatchEvent('formBEEP', _form=self)
-  
-  #---------------------------------------------------------------------------
-  # display a standard message box
-  #---------------------------------------------------------------------------
-  def triggerShowMessageBox (self, msgtxt, caption='GNUe Message',
+    # -------------------------------------------------------------------------
+
+    def triggerCommit(self):
+        """
+        Causes the form to commit
+        """  
+        event = events.Event('requestCOMMIT',_form=self)
+        self._instance.executeCommit(event)
+      
+    # -------------------------------------------------------------------------
+
+    def triggerBeep(self):
+        """
+        Tells the UI to beep (if possible)
+        
+        @return: None
+        """
+        self.dispatchEvent('formBEEP', _form=self)
+      
+    # -------------------------------------------------------------------------
+
+    def triggerShowMessageBox (self, msgtxt, caption='GNUe Message',
       title='Information', kind = 'Info', cancel = False):
-    """
-    Displays a standard message box.
-    @param msgtxt: text to be displayed
-    @param caption: caption to be displayed, default='GNUe Message'
-    @param title: title of messagebox, default='Information'
-    @param kind: 'Question', 'Info', 'Warning', or 'Error', default='Info'
-    @param cancel: Flag whether to include a Cancel button, default='False'
-    @return: True for <Yes> or <Ok> button, False for <No> button, None for
-        <Cancel> button.
-    """
-    return self._instance.displayMessageBox (msgtxt, kind, cancel, caption,
-                                             title)
+        """
+        Displays a standard message box.
+        @param msgtxt: text to be displayed
+        @param caption: caption to be displayed, default='GNUe Message'
+        @param title: title of messagebox, default='Information'
+        @param kind: 'Question', 'Info', 'Warning', or 'Error', default='Info'
+        @param cancel: Flag whether to include a Cancel button, default='False'
+        @return: True for <Yes> or <Ok> button, False for <No> button, None for
+            <Cancel> button.
+        """
+        return self._instance.displayMessageBox (msgtxt, kind, cancel, caption,
+                                                 title)
 
 
-  # --------------------------------------------------------------------------
-  # Show a message box using the given message
-  # --------------------------------------------------------------------------
-  def triggerMessageBox (self, message, kind = None, title = None,
-      cancel = False):
-    """
-    This function brings up a message box of a given kind.
-    @param message: text to be displayed
-    @param kind: 'Question', 'Info', 'Warning', or 'Error'
-    @param cancel: Boolean flag indicating wether a cancel button will be
-        included or not.
-    @return: True for <Yes> or <Ok> button, False for <No> button, None for
-        <Cancel> button.
-    """
-    return self._instance.displayMessageBox (message, kind, cancel, '', title)
+    # -------------------------------------------------------------------------
 
+    def triggerMessageBox (self, message, kind=None, title=None, cancel=False):
+        """
+        This function brings up a message box of a given kind.
+        @param message: text to be displayed
+        @param kind: 'Question', 'Info', 'Warning', or 'Error'
+        @param cancel: Boolean flag indicating wether a cancel button will be
+            included or not.
+        @return: True for <Yes> or <Ok> button, False for <No> button, None for
+            <Cancel> button.
+        """
+        return self._instance.displayMessageBox (message, kind, cancel, '',
+                title)
 
-  #---------------------------------------------------------------------------
-  # Switch input focus to a specfic entry widget
-  #---------------------------------------------------------------------------
-  def triggerSetFocus(self, object):
-    """
-    Switches input focus to a specific widget.
-    @param object: the widget that should get the focus
-    """
-    # add global focus locking
-    if self._in_trigger_lock:
-      print "Already called by a trigger"
-      return
 
-    self._in_trigger_lock = True
+    # -------------------------------------------------------------------------
 
-    focus = object._object
-    if focus._type == 'GFField':
-      try:
-        focus = focus._entryList[0]
-      except KeyError:
-        raise "setFocus failed: GFField is not bound to an GFEntry object."
+    def triggerSetFocus(self, object):
+        """
+        Switches input focus to a specific widget.
+        @param object: the widget that should get the focus
+        """
+        # add global focus locking
+        if self._in_trigger_lock:
+          print "Already called by a trigger"
+          return
 
-    if not focus._type in ['GFEntry', 'GFButton']:
-      raise "setFocus failed: Can just switch to GFEntry objects. " +\
-            "You passed a '%s' object." % focus._type
-    self.changeFocus(focus, 1)
-    self.dispatchEvent('gotoENTRY', object=self._currentEntry, _form=self)
-    self._in_trigger_lock = False
+        self._in_trigger_lock = True
 
+        focus = object._object
+        if focus._type == 'GFField':
+          try:
+            focus = focus._entryList[0]
+          except KeyError:
+            raise "setFocus failed: GFField is not bound to an GFEntry object."
 
-  #
-  # allow the trigger to get a handle to
-  # an actual GFBlock object
-  #
-  #
-  def triggerGetCurrentBlockName(self):
-    return self._currentBlock.name
-#   #
-#   # allow the trigger to get a handle to
-#   # an actual GFEntry object
-#   #
-#   # TODO: WHY?  This seems like a good way to write
-#   # TODO: triggers that break due to internal forms changes
-#   #
-#   def triggerGetCurrentEntry(self):
-#     return self._currentEntry
-#
-#
-#   #
-#   # allow the trigger to get a handle to
-#   # an actual GFBlock object
-#   #
-#   # TODO: WHY?  This seems like a good way to write
-#   # TODO: triggers that break due to internal forms changes
-#   #
-#   def triggerGetCurrentBlock(self):
-#     return self._currentBlock
-#
-#   #
-#   # allow the trigger to get a handle to
-#   # an actual GFPage object
-#   #
-#   # TODO: WHY?  This seems like a good way to write
-#   # TODO: triggers that break due to internal forms changes
-#   #
-#   def triggerGetCurrentPage(self):
-#     return self._currentPage
+        if not focus._type in ['GFEntry', 'GFButton']:
+          raise "setFocus failed: Can just switch to GFEntry objects. " +\
+                "You passed a '%s' object." % focus._type
+        self.changeFocus(focus, 1)
+        self.dispatchEvent('gotoENTRY', object=self._currentEntry, _form=self)
+        self._in_trigger_lock = False
 
 
-  #---------------------------------------------------------------------------
-  # Display a custom message on the form's status bar
-  #---------------------------------------------------------------------------
-  def triggerSetStatusText(self, tip=''):
-    """
-    Displays a custom message on the form's status bar.
-    @param tip: message to be displayed
-    @return: None
-    """
-    self._instance.updateStatusBar(tip=tip, form=self)
+    # -------------------------------------------------------------------------
+    def triggerGetCurrentBlockName(self):
+        return self._currentBlock.name
 
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Launch a new instance of gnue-forms running a different form.
-  #---------------------------------------------------------------------------
-  def triggerRunForm(self, fileName, parameters={}):
-    """
-    Launches a new instance of GNUe-Forms, running a different form.
-    @param fileName: the name of the .gfd file to be displayed
-    @param parameters: dictionary of parameters to be passed
-                        to the newly run form
-    @return: None
-    """
-    from GFInstance import GFInstance
-    instance = GFInstance(self._instance.manager,
-                          self._instance.connections,
-                          self._instance._uimodule,
-                          1,
-                          parameters=parameters)
-    instance.addFormFromFile(fileName)
-    #instance.addDialogs ()
-    instance.activate()
+    def triggerSetStatusText(self, tip=''):
+        """
+        Displays a custom message on the form's status bar.
+        @param tip: message to be displayed
+        @return: None
+        """
+        self._instance.updateStatusBar(tip=tip, form=self)
 
 
-  #---------------------------------------------------------------------------
-  # Launch a new instance of gnue-reports running a new report.
-  #---------------------------------------------------------------------------
-  def triggerRunReport(self, reportFile, parameters={}, **parms):
-    """
-    Launches a new instance of GNUe-Reports, running a new report.
-    @param reportFile: the name of the .grd file to be processed
-    @param parameters: dictionary of parameters to be passed
-                        to the newly run report
-    @param **params:
-      These roughly correspond to the ./gnue-reports options
-              destination
-              destinationType
-              destinationOptions (dict)
-              filter
-              filterOptions (dict)
-              sortoption
-              includeStructuralComments
-              omitGNUeXML
-    @return: None
-    """
-    from gnue.reports.base.GREngine import GREngine
-    from gnue.reports.base import GRFilters, GRExceptions
-    rep_engine = GREngine(self._instance.connections)
-    rep_engine.processReport(reportFile, parameters=parameters, **parms)
+    # -------------------------------------------------------------------------
 
+    def triggerRunForm(self, fileName, parameters={}):
+        """
+        Launches a new instance of GNUe-Forms, running a different form.
+        @param fileName: the name of the .gfd file to be displayed
+        @param parameters: dictionary of parameters to be passed
+                            to the newly run form
+        @return: None
+        """
+        from GFInstance import GFInstance
+        instance = GFInstance(self._instance.manager,
+                              self._instance.connections,
+                              self._instance._uimodule,
+                              1,
+                              parameters=parameters)
+        instance.addFormFromFile(fileName)
+        #instance.addDialogs ()
+        instance.activate()
 
-  #---------------------------------------------------------------------------
-  # Launch a standard or custom dialog
-  # Values can be passed back and forth thru the parameters dictionary
-  #---------------------------------------------------------------------------
-  def triggerActivateDialog (self, dialogName, parameters={}, modal=0):
-    """
-    Launches a standard or a custom dialog.
-    @param dialogName: name of the dialog to be displayed
-    @param parameters: dictionary of parameters used to pass values
-                        back and forth
-    @param modal: whether the dialog should be modal or not
-    @return: None
-    """
-    # Keep this to allow calling of about-box from trigger namespace
-    if dialogName == '_about':
-      self._instance._uiinstance.showAbout (**parameters)
-    else:
-      self._instance.activateForm (dialogName, parameters, modal)
+    # -------------------------------------------------------------------------
 
+    def triggerRunReport(self, reportFile, parameters={}, **parms):
+        """
+        Launches a new instance of GNUe-Reports, running a new report.
+        @param reportFile: the name of the .grd file to be processed
+        @param parameters: dictionary of parameters to be passed
+                            to the newly run report
+        @param **params:
+          These roughly correspond to the ./gnue-reports options
+                  destination
+                  destinationType
+                  destinationOptions (dict)
+                  filter
+                  filterOptions (dict)
+                  sortoption
+                  includeStructuralComments
+                  omitGNUeXML
+        @return: None
+        """
+        from gnue.reports.base.GREngine import GREngine
+        from gnue.reports.base import GRFilters, GRExceptions
+        rep_engine = GREngine(self._instance.connections)
+        rep_engine.processReport(reportFile, parameters=parameters, **parms)
 
 
-  #---------------------------------------------------------------------------
-  # Close this copy of gnue-forms
-  #---------------------------------------------------------------------------
-  def triggerClose(self):
-    """
-    Closes this copy of GNUe-Forms.
-    @return: None, or 1 if error
-    """
-    event = events.Event('requestEXIT', _form=self)
-    #self._instance.dispatchEvent(event)
-    self.dispatchEvent(event)
-    if event.__error__:
-      return 1
+    # -------------------------------------------------------------------------
 
+    def triggerActivateDialog (self, dialogName, parameters={}, modal=0):
+        """
+        Launches a standard or a custom dialog.
+        @param dialogName: name of the dialog to be displayed
+        @param parameters: dictionary of parameters used to pass values
+                            back and forth
+        @param modal: whether the dialog should be modal or not
+        @return: None
+        """
+        # Keep this to allow calling of about-box from trigger namespace
+        if dialogName == '_about':
+          self._instance._uiinstance.showAbout (**parameters)
+        else:
+          self._instance.activateForm (dialogName, parameters, modal)
 
-  #---------------------------------------------------------------------------
-  # Set feature values. Features are like toolbars, menubars, and statusbar
-  #---------------------------------------------------------------------------
-  def triggerSetFeature(self, feature, value):
-    """
-    Sets feature values.
-    Features are things like toolbars, menubars and statusbar.
-    @param feature: 'GUI:MENUBAR:SUPPRESS' or 'GUI:TOOLBAR:SUPPRESS' or
-                        'GUI:STATUSBAR:SUPPRESS'
-    @param value: True or False
-    @return: None
-    """
-    if not self._features.has_key(feature):
-      raise KeyError, "Trigger attempted to set unknown feature %s" % feature
-    else:
-      self._features[feature] = value
+    # -------------------------------------------------------------------------
+    def triggerClose(self):
+        """
+        Closes this copy of GNUe-Forms.
+        @return: None, or 1 if error
+        """
+        event = events.Event('requestEXIT', _form=self)
+        #self._instance.dispatchEvent(event)
+        self.dispatchEvent(event)
+        if event.__error__:
+          return 1
 
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # Get feature values. Features are like toolbars, menubars, and statusbar
-  #---------------------------------------------------------------------------
-  def triggerGetFeature(self, feature):
-    """
-    Gets feature values.
-    Features are things like toolbars, menubars and statusbar.
-    @param feature: 'GUI:MENUBAR:SUPPRESS' or 'GUI:TOOLBAR:SUPPRESS' or
-                        'GUI:STATUSBAR:SUPPRESS'
-    @return:    Boolean
-    """
-    try:
-      return self._features[feature]
-    except KeyError:
-      raise KeyError, "Trigger attempted to get unknown feature %s" % feature
+    def triggerSetFeature(self, feature, value):
+        """
+        Sets feature values.
+        Features are things like toolbars, menubars and statusbar.
+        @param feature: 'GUI:MENUBAR:SUPPRESS' or 'GUI:TOOLBAR:SUPPRESS' or
+                            'GUI:STATUSBAR:SUPPRESS'
+        @param value: True or False
+        @return: None
+        """
+        if not self._features.has_key(feature):
+          raise KeyError, "Trigger attempted to set unknown feature %s" % 
feature
+        else:
+          self._features[feature] = value
 
+    # -------------------------------------------------------------------------
 
-  #---------------------------------------------------------------------------
-  # TODO: Description
-  #---------------------------------------------------------------------------
-  def triggerGetAuthenticatedUser(self, connection=None):
-    """
-    Gets authenticated user.
-    """
-    return self._instance.connections.getAuthenticatedUser(connection)
+    def triggerGetFeature(self, feature):
+        """
+        Gets feature values.
+        Features are things like toolbars, menubars and statusbar.
+        @param feature: 'GUI:MENUBAR:SUPPRESS' or 'GUI:TOOLBAR:SUPPRESS' or
+                            'GUI:STATUSBAR:SUPPRESS'
+        @return:    Boolean
+        """
+        try:
+          return self._features[feature]
+        except KeyError:
+          raise KeyError, "Trigger attempted to get unknown feature %s" % 
feature
 
 
-  #---------------------------------------------------------------------------
-  # Set the title of the form.
-  #---------------------------------------------------------------------------
-  def triggerSetTitle(self, title):
-    """
-    Sets and displays the title of the form.
-    @param title: new title
-    """
-    self.title = title
-    # code to fire event to update the display goes here
-    self.dispatchEvent('setTitle', title=title, _form=self);
+    # -------------------------------------------------------------------------
 
+    def triggerGetAuthenticatedUser(self, connection=None):
+        """
+        Gets authenticated user.
+        """
+        return self._instance.connections.getAuthenticatedUser(connection)
 
-  #---------------------------------------------------------------------------
-  # Set a user parameter.
-  #---------------------------------------------------------------------------
-  def triggerSetParameter(self, parameter, value):
-    """
-    Sets a user parameter.
-    @param parameter: the (case-insensitive) name of the parameter to be set
-    @value: new value for parameter
-    """
 
-    # If _parameters are not yet set, fall back to the parameter dictionary of
-    # the GFInstance. This can only happen in ON-STARTUP triggers.
-    if not hasattr (self, '_parameters'):
-      self._parameters = self._instance._parameters
+    # -------------------------------------------------------------------------
 
-    # _parameters is a CaselessDict, so case of parameter doesn't matter
-    self._parameters [parameter] = value
+    def triggerSetTitle(self, title):
+        """
+        Sets and displays the title of the form.
+        @param title: new title
+        """
+        self.title = title
+        # code to fire event to update the display goes here
+        self.dispatchEvent('setTitle', title=title, _form=self);
 
 
-  #---------------------------------------------------------------------------
-  # Runs another trigger.
-  #---------------------------------------------------------------------------
-  def triggerActivateTrigger(self, name):
-    """
-    Runs another trigger.
-    @param name: name of the trigger to be run
-    """
-    self.processTrigger (name, False)
+    # -------------------------------------------------------------------------
 
+    def triggerSetParameter(self, parameter, value):
+        """
+        Sets a user parameter.
+        @param parameter: the (case-insensitive) name of the parameter to be 
set
+        @value: new value for parameter
+        """
+
+        # If _parameters are not yet set, fall back to the parameter 
dictionary of
+        # the GFInstance. This can only happen in ON-STARTUP triggers.
+        if not hasattr (self, '_parameters'):
+          self._parameters = self._instance._parameters
+
+        # _parameters is a CaselessDict, so case of parameter doesn't matter
+        self._parameters [parameter] = value
+
+
+    # -------------------------------------------------------------------------
+
+    def triggerActivateTrigger(self, name):
+        """
+        Runs another trigger.
+        @param name: name of the trigger to be run
+        """
+        self.processTrigger (name, False)

Modified: trunk/gnue-forms/src/GFInstance.py
===================================================================
--- trunk/gnue-forms/src/GFInstance.py  2006-04-07 06:55:42 UTC (rev 8390)
+++ trunk/gnue-forms/src/GFInstance.py  2006-04-07 09:21:49 UTC (rev 8391)
@@ -154,7 +154,7 @@
     mapping = {}
 
     for key in options.keys ():
-      if string.lower (key) [:4] == 'key_':
+      if key.lower ().startswith ('key_'):
         mapping [key [4:]] = options [key]
 
     GFKeyMapper.KeyMapper.loadUserKeyMap (mapping)

Modified: trunk/gnue-forms/src/GFObjects/__init__.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/__init__.py  2006-04-07 06:55:42 UTC (rev 
8390)
+++ trunk/gnue-forms/src/GFObjects/__init__.py  2006-04-07 09:21:49 UTC (rev 
8391)
@@ -39,7 +39,9 @@
         "GFLogic",
         "GFLayout",
         "GFParameter",
-        "GFComponent"
+        "GFComponent",
+        "GFTabStop",
+        "GFContainer"
        ]
 
 for module in __all__:

Modified: trunk/gnue-forms/src/uidrivers/_base/UIdriver.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/_base/UIdriver.py    2006-04-07 06:55:42 UTC 
(rev 8390)
+++ trunk/gnue-forms/src/uidrivers/_base/UIdriver.py    2006-04-07 09:21:49 UTC 
(rev 8391)
@@ -376,6 +376,7 @@
     index = entry._visibleIndex
     block = entry._block
     currentRecord = block._resultSet.getRecordNumber ()
+    uiWidget = entry.uiWidget
 
     # Fill the prior spots
     for count in range (index):
@@ -386,12 +387,12 @@
       value  = handler.getDisplayFiller (record.getField (field.field))
 
       assert gDebug (5, "UPD-ENTRY %s prior: '%s' (%s)" % (entry, value, 
count))
-      self._gfObjToUIWidget [entry].setValue (value, count)
+      uiWidget.setValue(value, count)
 
     # Fill current spot
     value = handler.getDisplayFiller (entry.getValue ())
     assert gDebug (5, "UPD-ENTRY %s current: '%s' (%s)" % (entry, value, 
index))
-    self._gfObjToUIWidget [entry].setValue (value, index)
+    uiWidget.setValue(value, index)
 
     # Fill trailing spots
     #
@@ -414,7 +415,7 @@
           value = handler.getDisplayFiller (rec.getField (field.field))
 
         assert gDebug (5, "UPD-ENTRY %s trail: '%s' (%s)" % (entry, value, 
count))
-        self._gfObjToUIWidget [entry].setValue (value, count, cr <= lastRow)
+        uiWidget.setValue(value, count, cr <= lastRow)
 
       count += 1
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]