Virtual self-reference


introduction framework patterns components conclusions references appendix experience
A special feature of the hush widget class library is its support for the definition of new composite widgets, which provide to the application programmer the interface of a built-in (or possibly other composite) widget. To realize this flexibility, we introduced a self() function that adds another level of indirection to self-reference. For example, we may define a drawtool widget, which provides for both the C++ programmer and the (Tcl) script programmer the interface of an ordinary (built-in) canvas:
    class drawtool: public canvas {
      public:
        drawtool() { }                  // to declare drawtool
        drawtool(char* path) {
  	initialize(path);             // constructs the components
  	redirect(_canvas);            // delegate to _canvas component
        }
        int operator()() {              // interface to Tcl
  	if (!strcmp("drawtool",argv[1])) return create(argc, argv);
  	else return self()->eval( flatten(argc, argv) );
        }
      private:
        void initialize(char* path); 
        int create(int argc, char* argv[]);
        canvas* _canvas;
    };
  
For completeness, the first constructor is only used to define the script command drawtool as in
    tk->bind("drawtool", new drawtool);
  
which may occur in main or prelude of the application class.

The call redirect(_canvas) in the regular constructor results in delegating both member function calls and script commands addressed at the drawtool widget to the canvas widget pointed to by _canvas, which is assumed to be created in initialize. The _canvas widget acts, so to speak, as the primary component of drawtool in that it receives all bindings and (configuration) commands. Actual redirection occurs by calling self(). The definition of widget::self() is simply:

    widget* self() { return _self?_self->self():this; }
  
In other words, it checks the private _self variable of the widget, which may be given a value by widget::_redirect, until _self is undefined (zero), in which case the this pointer is returned. In this way primary widget components can be embedded at arbitrary depth within a composite widget, without any need to adapt the interface of the embedding (composite) widget. Those well-versed in design patterns will recognize the Decorator patterns (as applied in the Interviews MonoGlyph class  [Interviews]).
introduction framework patterns components conclusions references appendix experience