Options for Basic Namespace Representation
------------------------------------------

 * Add <block>.field, <form>.<block>.<field>, <block>, <field>, etc 
   to namespace, and have a set of reserved words (properties, values,
   etc) to prevent namespace collisions.
   
     Advantages: 
       + Easiest to implement
       + Code will be fairly clean looking (readability)
       + Honors spirit of "objects"
       + Typical approach taken by most products in similar situation
   
     Disadvantages:
       + Places a larger burden on the end user as they must know and
         avoid reserved words. 
       + The reserved word list can (will?) grow, which could break 
         pre-existing triggers as our specification grows.
       + Only languages with support for object-oriented concepts can 
         be embedded.

     Notes: 
       + If the developer uses some standard for naming objects (as 
         designer does by default with standard prefixes [pg, dts, 
         blk, inp] ), then namespace collisions are not a concern.  
         However, not everyone uses standards
       

 * Add blocks.<block>.fields.<field> to namespace
 
     Advantages:
       + Easy to implement
       + Less namespace conflict than above method
       
     Disadvantages:
       + Code will be harder to read because of long object references.

     
 * Function-based lookups:   find("block.field")
   
     Advantages:
       + Will work in any language supporting functions (all modern?)
       + Easier to implement as only a few methods need to be added to an
       embedded language's namespace. 
       
     Disadvantages:
       + Creates UGLY code ('nuff said?)

     Notes:
       + Perhaps this should be the preferred implementation for non-object
         languages (scheme, etc) if an object-specific implementation is
	 selected


 * Pre-parsing tokens (:block.field)
 
     Advantages: 
       + Creates a consistent markup for all supported languages.
     
     Disadvantages: 
       + Depending on complexity, we may be creating a language on top of a
         language
       + The "object" referencing method (:block.field) might not be 
         consistant with the language's method (e.g, perl's: block->field)
       + The complexity of writing a pre-parser has yet to be determined

     Notes:
       sum(:main.token)
       setProperty(:main.token, 'Property','value')
       


Possible implementation layouts
-------------------------------

triggerManager
  trigger storage
  execute triggers
  loads engines

  parseTree()
    takes a GObj based object tree and creates a GTrigObj based tree from it
    the GTrigObj's are defined in individual applications along with a cross 
    reference to their GObj counterparts

    it extracts each defined trigger and creates trigger object
    it inits the needed triggerEngine

  executeTrigger()
    executes the requested trigger when given the name


 
? Do we need to do this?   
?  intended to be extended by each system using it 
?     (GFTriggerManager, GRTriggerManager)


triggerEngine
  high level interface that the manager uses to call triggers
  it hides the individual language engines

  baseEngine
    high level  API
    preprocessor
    namespace manipulation stubs

  possible Engines
    pythonEngine
    perlEngine
    tclEngine
    schemeEngine

trigger
  stores source and lang type
  stores compiled version (compiled by the engine)
  contains a state, list of arguments, output value
  passed into the engine when being processed
    when exits from engine the state can be checked 
    to verify trigger completed successfully


  
triggerExtension
  adds ability to run triggers to objects that inherit it
  
Scratchpad
----------

* All event triggers should return a success/fail value.

* Modify state of widgets:
    widget.properties.

* Direct datasource/result set access:

* Datasource/Block access
  firstRec, nextRec, prevRec, lastRec, etc

* block/field access:
    :block.field

* convenience functions:
    :block.sum(fieldname)
      .count(fieldname)
      .min/.max/.avg/


for i :=0 to datasource.field.count do
  mytotal = datasource.field[i]


if len(:currentBlock.zipcode):
  datasource1.clear()
  :datasource1.zipcode = :currentBlock.zipcode
  datasource1.query()
  currentBlock.FieldByName('city').
  :currentBlock.city = :datasource1.city
  :currentBlock.state = :datasource1.state
  for obj in currentblock
    obj.ReadOnly = true
    X = 10
  end


---------------------------
Jason's Scratchpad: 
---------------------------

Namespace Scope
---------------
(NOTE: This is partially language-dependent)


All Objects: 
 * "self" refers to the object containing the trigger (not the trigger 
   object).  For example, if a block contains a "pre-focusin" trigger, 
   then "self" within that trigger refers to the block.  This is true 
   even for named triggers.  (Python specific)


Global Namespace: 
 * all page names

 * all datasource names

 * all blocks???

 * "form" contains information specific to the current form (or "report", 
   etc).  Possible attributes for "form" are GetCurrentBlock(), 
   GetCurrentPage(), and GetCurrentField(), as well as all page names, 


Pages: 
 * All block, label, etc names located in the page (but not within blocks)


Blocks: 
 * all entry, label, etc names in the block

 * jump(#)   (Move to record #)

 * record()

 * first()

 * last()

 * isfirst()

 * islast()

 * count()

 

Fields: 
 * sum() adds all the fields 

 * count() returns a count of the fields that are non-null

 * 

  
========
findObject("myblock.myfield")

 * For non-OO languages
  
 * For object names that cause problems in namespace

========
Convenience functions: 
  myblock.field.sum()
  myblock.field.count()
  myblock.count()


========
How should we handle code other than triggers.



Object Translation Services???
------------------------------

 <input name="myfield">
   <import-trigger name="positiveTrigger"  ...  translate="field=myfield"/>
 </input> 
 
  ...

 <trigger name="positiveTrigger"> 
    if field.value < 0: 
      gnue.warn( "%s must be at least 0" % field.getDescription() )
      return 1
    else: 
      return 0
  </trigger>

  This way, positiveTrigger can be reused in many forms, even if the field 
  name changes.  




------------------------------------------------
James's Notes
------------------------------------------------

Extend GObj to add trigger support at this level


BEGIN: Custom namespace construction system

* Any object from the top level object is referenced by it's name

* a dictionary exists ()_triggerFunctions and will be populated by the GObj based 
  object's author.  It will contain references to functions

  _triggerFunctions = {
                         'exposedFunctionName', { 'function', functionlink,
                                                  'glcbal', function will be put in global namespace
                                                } 
                       }

  This will be used to construct the object tree described below

* Any object can tag itself as a global object which will make it available
  via it's name in the global namespace

* Any object can reference itself via a self. reference or it's own name

* A hook will be made available for internal properties manipulation these
  properties are available via __properties__ 

  _triggerProperties = {
                         'exposedPropertyName', { 'set', function that will set the value
                                                  'get', function that will get the value
                                                } 
                       }


  example :   form.block.__properties__.exposedPropertyName


* named triggers should be callable in a trigger

At init time the GObj tree is parsed.  The following objects are created to provide the 
trigger namespace.  Any objects found in the tree that request global
namespace assignment also get put into the global namespace.  

GTriggerObject
  * Created for each GObj that requires inclusion in the trigger namespace
  * Contains attributes that link to each of it's children's GTriggerObjects by their name
  * Contains attributes that link to GTriggerFunction and GTriggerAttribute objects
  * Contains the following extra attributes: 
  *   self
  *   __properties__

GTriggerFunction 
  * Created for each function that needs linked into a GTriggerObject
  * defines a __call__ that links to the stored link assigned by the GObj

GTriggerAttribute
  * Create for each attribute that needs linked into a GTriggerObject
  * defines __getattr__, __setattr__ that links to the assigned GObj variables 


In addition each GObj derived object contains a copy of the trigger namespace 
from itself down.  When a trigger is executed the global trigger namespace is merged 
with the local trigger namespace extracted from the object which is having the trigger
fired against it.

If a namespace conflict occurs then the local one wins out


GObj extensions
  _triggerGlobal : Always put this object in the global trigger namespace by it's name

  _triggerTransparent : Do not add this object to the trigger namespace however bump
                        it's children up to look as if they are assigned to this object's
                        parent in the trigger namespace.

  _triggerFunctions : the local trigger functions

  _triggerProperties : internal hooks into the GObj

END: Custom namespace construction system
