\c{

Configuring widgets

Widgets are the elements from which a GUI is made. They appear as windows on the screen to display text or graphics and may respond to events such as motioning the mouse or pressing a key by calling an action associated with that event. Usually, the various widgets constituting the user interface are (hierarchically) related to each other, such as in the drawtool application which contains a canvas to display graphic elements, a button toolbox for selecting the graphic items and a menubar offering various options such as saving the drawing in a file. } \c{ Widgets in Tk are identified by a path name. The path name of a widget reflects its possible subordination to another widget. See slide widget-hierarchy. } .so f_lay \c{ Pathnames consist of strings separated by dots. The first character of a path must be a dot. The first letter of a path must be lower case. The format of a path name may be expressed in BNF form as - ::= '.' | '.' | '.' For example `.' is the path name of the root widget, whereas `.quit' is the path name of a widget subordinate to the root widget. A widget subordinate to another widget must have the path name of that widget as part of its own path name. For example, the widget `.f.m' may have a widget `.f.m.h' as a subordinate widget. Note that the widget hierarchy induced by the path names is completely orthogonal to the widget class inheritance hierarchy depicted in slide hush-overview (a) and slide widget-classes. With respect to the path name hierarchy, when speaking of ancestors we simply mean superordinate widgets. } \c{ Pathnames are treated somewhat more liberally in hush. For example, widget path names may simply be defined or extended by a string. The missing dot is then automatically inserted. } .so sli-widget \c{ Calling the constructor widget as in widget* w = new widget(".awry"); does not result in creating an actual widget but only defines a pointer to the widget with that particular name. (It is not an abstract class, technically, since it does not contain any pure virtual functions, see section abstract-class.) If a widget with that name exists, it may be treated as an ordinary widget object, otherwise an error will occur. The constructor widget(widget* w,char* path) creates a widget by appending the path name path to the path name of the argument widget w. The function path delivers the path name of a widget object. Each widget created by Tk actually defines a Tcl command associated with the path name of the widget. In other words, an actual widget may be regarded as an object which can be asked to evaluate commands. For example a widget `.b' may be asked to change its background color by a Tcl command like .b configure -background blue The functions eval, result and evaluate enable the programmer to apply Tcl commands to the widget directly, as does the configure command. The function geometry sets the width and height of the widget. } \c{ Naming widgets in a hierarchical fashion does not imply that the widgets behave accordingly. The widget class interface offers two pack functions. The function widget::pack(char*) applies to individual widgets. As options one may specify, for example, {\tt -side X}, where {\tt X} is either top, bottom, left or right, to pack the widget to the appropriate side of the cavity specified by the ancestor widget. Other options are -fill x or -fill y, to fill up the space in the appropriate dimensions, or {\tt -padx N} or {\tt -pady N}, for some integer {\tt N}, to surround the widget with some extra space. Alternatively, the function widget::pack(widget*,char*) may be used, which allows for the same options but applies packing to the widget parameter. This function is convenient when packing widgets in a frame or toplevel widget. As a remark, the kit::pack function may only be used to pack widgets to the root window. } \c{

Binding events

Widgets may respond to events. To associate an event with an action, an explicit binding must be specified for that particular widget. Some widgets provide default bindings. These may, however, be overruled. The function bind is used to associate handlers or actions with events. The first string parameter of bind may be used to specify the event type. Common event types are, for example, {\tt ButtonPress}, {\tt ButtonRelease} and {\tt Motion}, which are the default events for canvas widgets. Also keystrokes may be defined as events, for example {\tt Return}, which is the default event for the entry widget. The function widget::handler may be used to associate a handler object or action with the default bindings for the widget. Concrete widgets may not override the handler function itself, but must define the protected virtual function install. Typically, the install function consists of calls to bind for each of the event types that is relevant to the widget. For both the bind and handler functions, the optional args parameter may be used to specify the arguments that will be passed to the handler or action when it is invoked. For the button widget, for example, the default install function supplies the text of the button as an additional argument for its handler. } \c{ In addition, the widget class offers four functions that may be used when defining compound or mega widgets. The function redirect(w) must by used to delegate the invocation of the eval, configure, bind and handler functions to the widget w. The function self() gives access to the widget to which the commands are redirected. After invoking redirect, the function thepath will deliver the path that is determined by self()->path(). In contrast, the function path will still deliver the path name of the outer widget. Calling redirect when creating the compound widget class suffices for most situations. However, when the default events must be changed or the declaration of a handler must take effect for several component widgets, the virtual function install must be redefined to handle the delegation explicitly. How redirect and install actually work will become clear in the examples. } .so termin