Contents Up Previous Next

wxCOOL overview

What is wxCOOL?
How to use the wxCOOL class reference
Instance creation
Types
wxCOOL event handling
Implementation details


What is wxCOOL?

Up until July 1995, wxCLIPS functionality was conceptually object-oriented, but solely implemented using CLIPS functions. Since the only way to couple CLIPS to C or C++ programs is by defining user functions, the functional route is a prerequisite. wxCOOL is a set of CLIPS classes built on top of the user functions, encapsulating most of the wxCLIPS functionality for which it is sensible to do so. At present, it is not quite complete. wxCOOL resides in the wxcool subdirectory of the wxCLIPS installation directory, and is loaded by batching the file wx.clp. Before using the classes, you need to call the function wxcool-init.

Because wxCOOL is implemented in terms of the wxCLIPS functions, it does add overhead to a CLIPS application in terms of loading time, execution speed, and (to a less significant degree) memory requirements. So you may still wish to code speed-critical parts of your application using the raw wxCLIPS functions, especially where a lot of GUI elements are to be created.

Saving your application as a binary file will certainly speed up loading time (and help protect your source code from prying eyes) but there may be a size limit on binary files under MS Windows (as yet undetermined). Another problem is that you cannot load a binary file and then load non-binary constructs: it's all-or-nothing.


How to use the wxCOOL class reference

In the message handler definitions, bold words are types, and are not part of CLIPS syntax. Parameter names are in italics. Types are as follows:

Parameters can be optional, in which case defaults are assumed.

Some parameters can be combinations ('bit lists') of flags. wxCLIPS mimics the compact C++ syntax by parsing strings, for example:

  (make-instance (gensym*) of wxFrame (style "wxSDI | wxDEFAULT")
     ...)
Each identifier in such a parameter is translated to an integer value, and all are logical-or'ed together to produce an integer which is passed to the appropriate wxWindows C++ function.

Slots are listed before the message handlers.

Accessors (put-... and get-... functions) are not documented explicitly, but can be assumed where appropriate: see the documentation for each class's slots.

Create handlers for each class are documented, but are not explicitly called by the programmer: they are called by the init handler on instance creation. You can use call-next-handler from within a Create handler, to ensure all ancestors get a chance to initialise. However, you should not invoke call-next-handler in a 'delete' handler since CLIPS calls this for each class anyway.


Instance creation

Instance creation is done in the conventional CLIPS way, e.g.

 (make-instance test1 of MyFrame (title "Hello world!") (x 20) (y 20) (width 200) (height 200))
Slot initializers take the place of function parameters, which makes for more legible code, albeit for instance creation only, and not normal message passing.

Each class has a message handler called 'create', which constructs the underlying object and adds callbacks for the instance. The initialization code cannot be put into the standard 'init' handler for each class, since this is called for every class that an instance inherits from, and would result in multiple wxCLIPS objects being created for one instance. Instead, there is one init handler for wxObject which sends a create message to the object, and create is redefined for each class.

Note that the integer identifier of the underlying wxCLIPS object can be retrieved with the get-id accessor.


Types

wxCLIPS uses integers for various purposes, including boolean values. This is inconvenient in CLIPS applications, which normally use the symbolic values TRUE and FALSE. Accordingly, all wxCOOL boolean values are now symbolic (TRUE or FALSE). wxCOOL will not work correctly if you attempt to use integers instead of symbolic values.


wxCOOL event handling

wxCOOL function callbacks and events work differently from wxCLIPS callbacks and events. Instead of adding callbacks for events such as on-menu-command, you override the default event handler. All window objects derive from the class wxEvtHandler, which contains default handlers for all window callbacks. A window will normally process its own messages, so you would for example add an on-menu-command handler to your wxFrame-derived class. However, you can use the put-event-handler message to set the event handler to be a different instance of wxEvtHandler. So, you could avoid deriving from a window class altogether, and have one class which accepts the events from a variety of windows.

Panel items no longer require callback functions to be specified on creation. Instead, panel item events are sent as an on-command message to the panel item. The default wxItem on-command handler sends the message to its parent wxPanel, so you could derive a new class from wxPanel to receive on-command events, or set the item's event handler to direct it to a different instance.

The on-command handler takes wxItem instance and wxCommandEvent instance parameters. A convenient way of distinguishing incoming events is to give an item a name on creation, and test for that name in the on-command handler, using the get-name accessor.


Implementation details

From version 1.42, wxCLIPS has a few built-in functions to aid in maintaining a parallel set of classes corresponding to the underlying wxCLIPS classes (and ultimately, C++ classes). The instance table functions help map between integer identifiers and CLIPS instance names. When an instance is constructed, the underlying wxCLIPS object is created and this id added to the instance table. On deletion, the entry is removed from the instance table. Callbacks are defined, such as gui-window-on-close, that are used for all instances of a class (and derived classes); they use instance-table-get-instance to retrieve the instance corresponding to the wxCLIPS object.

wxCLIPS sends OnDelete callbacks to the application when a wxCLIPS object is being deleted. This is exploited in wxCOOL to ensure that wxCOOL instances are cleaned up if wxCLIPS, and not the CLIPS application, deletes wxCLIPS objects. The twist is that we need to distinguish between an application-initiated deletion, for which we wish to call a function such as window-delete, and a wxCLIPS-initiated deletion, for which window-delete is effectively being called implicitly. To avoid deleting objects twice, wxCOOL sets a pending-delete slot in the object which is tested before deleting the underlying object.

In some cases, all deletions of a class's objects are initiated by wxCLIPS: for example, wxMenu instances will be deleted by the parent wxMenuBar, which is deleted implicitly when the wxFrame is deleted.