Application development generally encompasses a variety of programming tasks, including system-level software development (for example for networking or multimedia functionality), programming the user interface (including the definition of screen layout and the responsivity of the interface widgets to user actions), and the definition of (high-level) application-specific functionality. Each of these kinds of tasks may require a different approach and possibly a different application programming language. For example, the development of the user interface is often more conveniently done using a scripting language, to avoid the waiting times involved in compiling and linking. Similarly, defining knowledge-level application-specific functionality may benefit from the use of a declarative or logic programming language.
In our project, we decided from the start to support a multiparadigm approach to software development and consequently we had to define the mutual interaction between the various language paradigms, as for example the interaction between C++ and a scripting language, such as Tcl. Current scripting languages, including Python and Tcl, provide facilities for being embedded in C and C++, but extending these languages with functionality defined in C or C++ and employing the language from within C/C++ is rather cumbersome. What we need is a simple and generic mechanism to associate script commands with actions defined by the application and (inversely) a generic way to employ scripting facilities in the application.
interface kit { void eval(char* cmd); char* result(); void action(char* name, handler* h); };The function eval is used for evaluating (script) commands, and result may be used to communicate data back. The limitation of this approach, obviously, is that it is purely string based. In practice, however, this proves to be flexible and sufficiently powerful. The action function may be used to define new commands and associate it with functionality defined in handler objects, that will be introduced soforth.
interface handler : client { int dispatch( event* e );The dispatch function is called by the underlying system. (In effect, a standard callback function is used with the handler object as client data, which explains why the handler object inherits from the class client.) The dispatch function receives a pointer to a sytsem-defined event which encodes the information relevant for that particular callback. In its turn dispatch calls the application operator. Classes derived from handler need only redefine the operator() function. Information needed when activating a handler object must be provided when creating the object, or obtained from the event for which the handler is activated.to dispatch event
int operator()(); };
The use of handler objects is closely connected to the paradigm of event-driven computation. An event, conceptually speaking is an entity that is characterized by two significant moments, the moment of its creation and the moment of its activation, its occurrence Naturally, an event may be activated multiple times and even record a history of its activation, but the basic principle underlying the use of events is that all the information that is needed is stored at creation time and, subsequently, activation may proceed blindly.
interface widget : handler { ... void bind( handler* h ); void bind( char* user, handler* h ); ... };The first member function bind may be used for installing a handler for the default bindings of the widget, whereas the second bind function is to be used for overriding any specific bindings. (Notice that the class widget is derived from handler class to allow the widget to be its own handler. In this way inheritance or the delegation to a separate handler object may be used to define the functionality of a widget.)
In addition to the widget class, the hush library also provides the class item, representing graphical items. Graphical items, however, are to be placed within a canvas widget, and may be tagged to allow for the groupwise manipulation of a collection of items, as for example moving them in response to dragging the mouse pointer.
interface event : handler { operator()(); };Actual event classes are derived from the generic class event, and a scheduler is provided to activate events at the appropriate time. (In effect, we provide a fully functional discrete event simulation library, including facilities for generating random distributions and analysing the outcome of experiments.) Note that there is an important difference between user-defined events and system-defined events. System-defined events are delivered to the user by activating a handler callback. In contrast, user-defined events are (directly) activated by a scheduler. They contain, so to speak, their own handler.