Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ Template(3X) — DeltaWindows 1.3.3 Release 4 Version 4.3

Media Vault

Software Library

Restoration Projects

Artifacts Sought

 

NAME

Template widget − widget to create a custom widget. 

SYNOPSIS

Public Headers:<X11/StringDefs.h> <X11/Xaw/Template.h>

Private Header:<X11/Xaw/TemplateP.h>

Class Name:Template

Class Pointer:templateShellWidgetClass

Instantiation:This widget in not normally instantiated until you write your own functionality for it. 

DESCRIPTION

Although the task of creating a new widget may at first appear a little daunting, there is a basic pattern that all widgets follow.  The Athena widget library contains three files that are intended to assist in writing a custom widget:  Template.h, TemplateP.h, and Template.c.  However, it may be easier to start with a widget that has more real code to copy and modify. 

Reasons for wishing to write a custom widget include:

•Convenient access to resource management procedures to obtain fonts, colors, etc., even if user customization is not desired. 

•Convenient access to user input dispatch and translation management procedures. 

•Access to callback mechanisms for building higher-level application libraries. 

•Customizing the interface or behavior of an existing widget to suit a special application need. 

•Desire to allow user customization of resources such as fonts, colors, etc., or to allow convenient re-binding of keys and buttons to internal functions. 

•Converting a non-Toolkit application to use the Toolkit. 

In each of these cases, the operation needed to create a new widget is to "subclass" an existing one.  If the desired semantics of the new widget are similar to an existing one, then the implementation of the existing widget should be examined to see how much work would be required to create a subclass that will then be able to share the existing class methods.  Much time will be saved in writing the new widget if an existing widget class’s Expose, Resize, and/or GeometryManager method can be shared by the subclass. 

Note that some trivial uses of a "bare-bones" widget may be achieved simply by creating an instance of the Core widget.  The class variable to use when creating a Core widget is widgetClass.  The geometry of the Core widget is determined entirely by the parent widget. 

Often, an application will need a certain set of functions—and many copies of them.  For example, when converting an older application to use the Toolkit, it may be desirable to have a "Window widget" class that might have the following semantics:

•Allocate two drawing colors in addition to a background color. 

•Allocate a text font. 

•Execute an application-supplied function to handle exposure events. 

•Execute an application-supplied function to handle user input events. 

Of course, a completely general-purpose WindowWidgetClass could be constructed to export all class methods as callback lists, but such a widget would be very large and would have to choose some arbitrary number of resources, such as colors, to allocate.  An application that used many instances of the general-purpose widget would therefore waste many resources unnecessarily. 

This section outlines the procedure to follow to construct a special-purpose widget to address the items listed above. The reader should refer to the appropriate sections of VOL4], for complete details of the material outlined here.

All Athena widgets have three separate files associated with them:

•A public header file containing declarations needed by applications programmers. 

•A private header file containing additional declarations needed by the widget and any subclasses. 

•A source code file containing the implementation of the widget. 

This separation of functions into three files is suggested for all widgets, but nothing in the Toolkit actually requires this format.  In particular, a private widget created for a single application may easily combine the public and private header files into a single file, or merge the contents into another application header file.  Similarly, the widget implementation can be merged into other application code. 

In the following example, the public header file <X11/Xaw/Template.h>, the private header file <X11/Xaw/TemplateP.h>, and the source code file <X11/Xaw/Template.c> are modified to produce the Window widget described above.  In each case, the files have been designed so that you can make a global string replacement of Template and template with the name of your new widget, using the appropriate case. 

PUBLIC HEADER FILE

The public header file contains declarations that will be required by any application module that needs to refer to the widget; whether to create an instance of the class, to perform an XtSetValues() operation, or to call a public routine implemented by the widget class. 

The contents of the Template public header file, <X11/Xaw/Template.h>, are: #ifndef _Template_h #define _Template_h
 
/∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
 ∗
 ∗ Template widget
 ∗
 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗/
 
/∗ Resources:
 
 NameClassRepTypeDefault Value
 -----------------------------
 backgroundBackgroundPixelXtDefaultBackground
 borderBorderColorPixelXtDefaultForeground
 borderWidthBorderWidthDimension1
 destroyCallbackCallbackPointerNULL
 heightHeightDimension0
 mappedWhenManagedMappedWhenManaged Boolean TRUE
 sensitiveSensitiveBooleanTRUE
 widthWidthDimension0
 xPositionPosition0
 yPositionPosition0
 
∗/
 
/∗ define any special resource names here ∗
 ∗ that are not in <X11/StringDefs.h> ∗/
 
#define XtNtemplateResource"templateResource"
 
#define XtCTemplateResource"TemplateResource"
 
/∗ declare specific TemplateWidget class and instance datatypes ∗/
 
typedef struct _TemplateClassRec∗TemplateWidgetClass; typedef struct _TemplateRec∗ TemplateWidget;
 
/∗ declare the class constant ∗/
 
extern WidgetClass templateWidgetClass;
 
#endif  _Template_h You will notice that most of this file is documentation.  The crucial parts are the last 8 lines, where macros for any private resource names and classes are defined and where the widget class datatypes and class record pointer are declared.

For the Window widget, we want two drawing colors, a callback list for user input and an XtNexposeCallback callback list, and we will declare three convenience procedures, so we need to add: /∗ Resources:  ... 
 callbackCallbackCallbackNULL
 drawingColor1ColorPixelXtDefaultForeground
 drawingColor2ColorPixelXtDefaultForeground
 exposeCallbackCallbackCallbackNULL
 fontFontXFontStruct∗XtDefaultFont  ... 
 ∗/
 
#define XtNdrawingColor1"drawingColor1" #define XtNdrawingColor2 "drawingColor2" #define XtNexposeCallback "exposeCallback"
 
extern Pixel WindowColor1(/∗ Widget ∗/); extern Pixel WindowColor2(/∗ Widget ∗/); extern Font  WindowFont(/∗ Widget ∗/); Note that we have chosen to call the input callback list by its generic name, XtNcallback, rather than by a specific name.  If widgets that define a single user-input action all choose the same resource name, then there is greater possibility for an application to switch between widgets of different types. 

PRIVATE HEADER FILE

The private header file contains the complete declaration of the class and instance structures for the widget and any additional private data that will be required by anticipated subclasses of the widget.  Information in the private header file is normally hidden from the application and is designed to be accessed only through other public procedures, such as XtSetValues(). 

The contents of the Template private header file, <X11/Xaw/TemplateP.h>, are: #ifndef _TemplateP_h #define _TemplateP_h
 
#include "Template.h" /∗ include superclass private header file ∗/ #include <X11/Xaw/CoreP.h>
 
/∗ define unique representation types not found in <X11/StringDefs.h> ∗/
 
#define XtRTemplateResource"TemplateResource"
 
typedef struct { int empty; } TemplateClassPart;
 
typedef struct _TemplateClassRec {  CoreClassPart core_class;  TemplateClassPart template_class; } TemplateClassRec;
 
extern TemplateClassRec templateClassRec;
 
typedef struct { /∗ resources ∗/  char∗ resource;  /∗ private state ∗/ } TemplatePart;
 
typedef struct _TemplateRec {  CorePart core;  TemplatePart template; } TemplateRec;
 
#endif  _TemplateP_h The private header file includes the private header file of its superclass, thereby exposing the entire internal structure of the widget. It may not always be advantageous to do this; your own project development style will dictate the appropriate level of detail to expose in each module.

The Window widget needs to declare two fields in its instance structure to hold the drawing colors—a resource field for the font, and a field for the expose and user input callback lists: typedef struct {  /∗ resources ∗/  Pixel color_1;  Pixel color_2;  XFontStruct∗ font;  XtCallbackList expose_callback;  XtCallbackList input_callback;  /∗ private state ∗/  /∗ (none) ∗/ } WindowPart;

WIDGET SOURCE FILE

The source code file implements the widget class itself.  The unique part of this file is the declaration and initialization of the widget class record structure and the declaration of all resources and action routines added by the widget class. 

The contents of the Template implementation file, <X11/Xaw/Template.c>, are: #include <X11/IntrinsicP.h> #include <X11/StringDefs.h> #include "TemplateP.h"
 
static XtResource resources[] = { #define offset(field) XtOffset(TemplateWidget, template.Peeld)  /∗ {name, class, type, size, offset, default_type, default_addr}, ∗/  { XtNtemplateResource, XtCTemplateResource, XtRTemplateResource, \&\  sizeof(char∗), offset(resource), XtRString, "default" }, #undef offset };
 
static void TemplateAction(/∗ Widget, XEvent∗, String∗, Cardinal∗ ∗/);
 
static XtActionsRec actions[] = {  /∗ {name, procedure}, ∗/  {"template", TemplateAction}, };
 
static char translations[] = " <Key>: template() \n\ ";
 
TemplateClassRec templateClassRec = {

{/∗ core fields ∗/ /∗ superclass ∗/ (WidgetClass) &widgetClassRec,  /∗ class_name ∗/ "Template",  /∗ widget_size ∗/ sizeof(TemplateRec),  /∗ class_initialize ∗/ NULL,  /∗ class_part_initialize ∗/ NULL,  /∗ class_inited ∗/ FALSE,  /∗ initialize ∗/ NULL,  /∗ initialize_hook ∗/ NULL,  /∗ realize ∗/ XtInheritRealize,  /∗ actions ∗/ actions,  /∗ num_actions ∗/ XtNumber(actions),  /∗ resources ∗/ resources,  /∗ num_resources ∗/ XtNumber(resources),  /∗ xrm_class ∗/ NULLQUARK,  /∗ compress_motion ∗/ TRUE,  /∗ compress_exposure ∗/ TRUE,  /∗ compress_enterleave ∗/ TRUE,  /∗ visible_interest ∗/ FALSE,  /∗ destroy ∗/ NULL,  /∗ resize ∗/ NULL,  /∗ expose ∗/ NULL,  /∗ set_values ∗/ NULL,  /∗ set_values_hook ∗/ NULL,  /∗ set_values_almost ∗/ XtInheritSetValuesAlmost,  /∗ get_values_hook ∗/ NULL,  /∗ accept_focus ∗/ NULL,  /∗ version ∗/ XtVersion,  /∗ callback_private ∗/ NULL,  /∗ tm_table ∗/ translations,  /∗ query_geometry ∗/ XtInheritQueryGeometry,  /∗ display_accelerator ∗/ XtInheritDisplayAccelerator,  /∗ extension ∗/ NULL }, { /∗ template fields ∗/  /∗ empty ∗/ 0 }

};
 
WidgetClass templateWidgetClass = (WidgetClass)&templateClassRec; The resource list for the Window widget might look like the following: static XtResource resources[] = { #define offset(field) XtOffset(WindowWidget, window.Peeld)  /∗ {name, class, type, size, offset, default_type, default_addr}, ∗/  { XtNdrawingColor1, XtCColor, XtRPixel, sizeof(Pixel),    offset(color_1), XtRString, XtDefaultForeground },  { XtNdrawingColor2, XtCColor, XtRPixel, sizeof(Pixel),    offset(color_2), XtRString, XtDefaultForeground },  { XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct∗),    offset(font), XtRString, XtDefaultFont },  { XtNexposeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),    offset(expose_callback), XtRCallback, NULL },  { XtNcallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),    offset(input_callback), XtRCallback, NULL }, #undef offset }; The user input callback will be implemented by an action procedure that passes the event pointer as call_data.  The action procedure is declared as:

/∗ ARGSUSED ∗/ static void InputAction(w, event, params, num_params)  Widget w;  XEvent ∗event;  String ∗params; /∗ unused ∗/  Cardinal ∗num_params; /∗ unused ∗/ {  XtCallCallbacks(w, XtNcallback, (caddr_t)event); }
 
static XtActionsRec actions[] = {  /∗ {name, procedure}, ∗/  {"input", InputAction}, };

and the default input binding will be to execute the input callbacks on KeyPress and ButtonPress:

static char translations[] = " <Key>: input() \n\
 <BtnDown>: input() \ ";

In the class record declaration and initialization, the only field that is different from the Template is the expose procedure: /∗ ARGSUSED ∗/ static void Redisplay(w, event, region)  Widget w;  XEvent ∗event;   /∗ unused ∗/  Region region; {  XtCallCallbacks(w, XtNexposeCallback, (caddr_t)region); } WindowClassRec windowClassRec = {  ...   /∗ expose ∗/  Redisplay, The Window widget will also declare three public procedures to return the drawing colors and the font ID, saving the application the effort of constructing an argument list for a call to XtGetValues():

Pixel WindowColor1(w)  Widget w; {  return ((WindowWidget)w)->window.color_1; }
 
Pixel WindowColor2(w)  Widget w; {  return ((WindowWidget)w)->window.color_2; }
 
Font WindowFont(w)  Widget w; {  return ((WindowWidget)w)->window.font->fid; }

The Window widget is now complete.  The application can retrieve the two drawing colors from the widget instance by calling either the XtGetValues() or the WindowColor functions.  The actual window created for the Window widget is available by calling the XtWindow() function. 

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026