Decorators in TIScript, fun of UI programming is back.

Latest builds of the Sciter have decorators implemented. My implementation of decorators ideologically derived from the same decorator feature in Python of Guido van Rossum.

Decorators is a meta/macro-programming feature that allows to transform or update function or class defined in source code.

Here is an example: say we are designing some dialog with various input elements and buttons. Usually code behind such dialogs is a collection of simple “if-we’ve-got-some-event-here-then-update-state-over-there” blocks. First part (if-we’ve-got-some-event-here…) of the task is repeating again and again. The desire is to make it as short and clear as possible. With decorators this could be written as:

@when Event.BUTTON_CLICK @on "button#add-new" :
   {
      this.select("#list").insert( new Element( "option", "new item") );
   }
@when Event.SELECT_SELECTION_CHANGED @on "select#list" :
   {
      this.select("#delete-current").state.enabled = true;
   }
...

This makes such sequence of blocks to look more like a table of records: when (event) on (where) (then do this). That is more declarative approach if you wish. This code is better maintainable I think.

@when and @on here are decorators of anonymous function that follow them. ( Sequence :{ ... } declares anonymous function in TIScript ).

Decorator in TIScript is an ordinary function with the name starting ‘@’ and at least one parameter. This first parameter is a reference to function that is being decorated. Decorator-function in its turn can dynamically create another function that will wrap call of original function.

Here is how our @when and @on decorators might look like:

// decorator '@when' - filters event by type 
function @when(func, evtType)
    {
      return self.onControlEvent = function(evt)
         {
           if( evt.type == evtType) 
              return func.call(this,evt);
         }
    }

// decorator '@on' - filters evt.target by the selector
function @on(func, selector)
    {
      return function(evt)
      {
        if( evt.target.match(selector) ) // if target element matches 
          return func.call(this,evt);       // the selector call the func. 
      }
    }

Chain of decoratorsAs you may see both decorators simply create wrapper functions that filter the event using different criteria. Thus following statement:

@when Event.BUTTON_CLICK @on "button#add" :{...code...}

simply establishes chain of filters that ends up with the call of code that handles the event.

Syntax of decorators in TIScript is described here.