3. Composite Widgets
Box Widget
- we have already seen the box widget, this widget places its children in a rather
arbitrary way, the programmer has little control over how they are placed
- this widget works well for simple layouts such as button boxes
Paned Widget
- the paned widget gives us more control over how the child widgets are handled
- in a paned widget the child widgets are treated as tiles and these tiles are laid out
horizontally or vertically depending on the value of the orientation resource
- each of the child widgets can have a grip associated with it, this grip is associated
with either the bottom or right side of the widget, depending upon the pane orientation
- the user can grab the grip and move the corresponding side of the widget, when this
happens the widgets in the pane move or resize, depending upon how their resources are set
- the paned widget allows the user to control the size of the child widgets, and the
programmer has some control over how the child widgets are resized, note that a resize
could also occur when the user changes the size of the paned widget itself
- the main resource of interest in the paned widget is the orientation resource, which can
have the values XorientHorizontal or XorientVertical, this controls the direction in which
the child widgets are tiled
- when a paned widget is used a collection of constraint resource is added to the child
widgets, these resources specify how the child widget changes when the parent changes
size, or one of the other child widgets changes size
- we use the constraint resources to control the layout of the child widget
- the showGrip resource specifies whether a grip is associated with the child, if there is
no grip the user can't directly resize the child
- the min and max resources state the minimum and maximum sizes for the widget, in the
case of a horizontal orientation this is the height of the widget, otherwise it is the
width of the widget
- the widget will never be smaller than its min resource or larger than its max resource
- the preferredPaneSize resource contains the preferred size of the widget, it will always
try to be this size
- if the skipAdjust resource is set to True, the pane will be less likely to be resized,
the paned widget will attempt to resize other child object first
- there are convenience routines that can be used to set most of these resources
- there are three layout rules that are used when a child widget is resized using a grip,
these rules are:
- the pane must be between its min and max size
- do not adjust panes with skipAdjust set
- do not adjust panes away from their preferred size, moving towards the preferred size is
better
- rule (1) is never broken, the other two are not always followed and rule (2) has
priority over rule (3)
- to see how these rules operate consider the case of a vertical paned widget, and the
user grabs the grip for one of the child widgets, the user can move the grip in one of two
directions
- if the user moves the grip upwards the child widget will get smaller, all the widget
above the child widget will stay the same size, and the widgets below the child will be
resized
- if the user moves the grip downwards, the child widget below the grip will get smaller,
all the widget below this child will stay the same size, all the widgets above this child
will resize (they could get larger)
- if after all resizing has been attempted and some of the widgets don't fit in the paned
widget, they aren't displayed
/*****************************************************
*
* composite.c
*
* A very simple X program that shows how the composite
* widgets in the Athena widget set are used
*
* This program constructs a paned widget that has
* three children. Each of the children is a box
* widget that contains a quit button. All three of
* the children can be resized.
*
****************************************************/
#include < X11/StringDefs.h >
#include < X11/Intrinsic.h >
#include < X11/Xaw/Paned.h >
#include < X11/Xaw/Box.h >
#include "../lib/lib.h"
main(argc,argv)
int argc;
char **argv; {
Widget toplevel;
Widget paned;
Widget box1, box2, box3;
Widget quit1, quit2, quit3;
Arg wargs[10];
int n;
toplevel = XtInitialize(argv[0],"simple",NULL, 0,
&argc, argv);
paned = XtCreateManagedWidget("paned",panedWidgetClass,
toplevel, NULL, 0);
box1 = XtCreateManagedWidget("box1",boxWidgetClass,
paned, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNmin, 25); n++;
XtSetArg(wargs[n], XtNmax, 75); n++;
XtSetArg(wargs[n], XtNpreferredPaneSize, 50); n++;
XtSetValues(box1,wargs,n);
quit1 = quit_button(box1);
box2 = XtCreateManagedWidget("box2",boxWidgetClass,
paned, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNmin, 25); n++;
XtSetArg(wargs[n], XtNmax, 75); n++;
XtSetArg(wargs[n], XtNpreferredPaneSize, 50); n++;
XtSetValues(box2,wargs,n);
quit2 = quit_button(box2);
box3 = XtCreateManagedWidget("box3",boxWidgetClass,
paned, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNmin, 25); n++;
XtSetArg(wargs[n], XtNmax, 75); n++;
XtSetArg(wargs[n], XtNpreferredPaneSize, 50); n++;
XtSetValues(box3,wargs,n);
quit3 = quit_button(box3);
XtRealizeWidget(toplevel);
XtMainLoop();
}
Form Widget
- the form widget provide a flexible mechanism for the layout of its child widgets
- each child widget can specify the widget is that is to its left or above it, it can also
specify how it changes shape when the form widget changes shape
- the form widget itself only has one new resource, which is defaultDistance, this is the
default distance between the child widgets when they are placed in the form widget
- there are a number of constraint resources that are added to each of the child widget
- the fromHoriz and fromVert resources control the initial layout of the child widgets,
you will need to specify values for at least one of these resources for almost all the
child widgets
- the value of the fromHoriz resource is the widget id for the widget that is to the left
of the current widget, this can be used to string out the widgets from left to right
- similarly, the valueof the fromVert resource is the widget id of the widget that is
above the current widget, this can be used to string out the widgets from top to bottom
- if a value isn't specified for one of these resource than it is assumed that the
programmer wants the widget to be against the edge of the form widget, if values aren't
specified for these resources the widgets will appear on top of each other and only the
first widget will be visible
- the value of the fromHoriz and fromVert resource must be a widget that has already been
created, when the form widget does the layout it only performs one pass through the list
of widgets, so it can't handle forward references or circular structures
- the horizDistance resource specifies the distance from the left neighbour (in pixels)
and the vertDistance specifies the distance from the top neighbour (in pixels) if values
for these resources aren't specified the value of defaultDistance is used
- after the initial layout is performed a second set of resources and a different
algorithm is used to control the layout of the child widgets
- the second algorithm is based on specifying how the edges of the child widget move when
the edges of form widget move, that is how does the child wdiget change size when the
parent widget changes size
- for each edge there are two possibilities, either the edge stays where it is (a fixed
distance from one of the form widget edges) or it moves as the corresponding edge on the
form widget moves
- the following resources are used to specify this behavior
- the top, bottom, left and right resources are used to specify what happens with the
corresponding edge of the child widget, in other words the value of the right resource
specifies how the right edge of the child widget behaves when the form widget is resized
- there are 5 possible values for these resources, the default values is XtRubber, when
this value is used the edge of the child widget moves with the corresponding edge of the
form widget
- for example if the value of the top resource is XtRubber then when the top of the form
widget is moved by 50% the top edge of the child widget will also move by 50%
- if all the edges have XtRubber as their value then the child widget will scale with the
form widget, if the form widget doubles in size the child widget will also double in size,
etc
- the remaining four values specify that the edge stays a constant distance for one of the
edges of the form widget, these values are: XtChainBottom, XtChainTop, XtChainLeft and
XtChainRight
- for example if the value of the top resource is XtChainTop the top of the child widget
will always stay a fixed distance from the top of the form widget
- these resource values are used to keep the child widget the same size and follow the
edge of the form widget
/*****************************************************
*
* composite.c
*
* A very simple X program that shows how the composite
* widgets in the Athena widget set are used
*
* This program constructs a form widget that has
* several children. Each of the children is a box
* widget that contains a quit button. The three
* children have different constraint resources
* and show how they can be used.
*
****************************************************/
#include < X11/StringDefs.h >
#include < X11/Intrinsic.h >
#include < X11/Xaw/Form.h >
#include < X11/Xaw/Box.h >
#include "../lib/lib.h"
main(argc,argv)
int argc;
char **argv; {
Widget toplevel;
Widget form;
Widget box1, box2, box3;
Widget quit1, quit2, quit3;
Arg wargs[10];
int n;
toplevel = XtInitialize(argv[0],"simple",NULL, 0,
&argc, argv);
n = 0;
XtSetArg(wargs[n],XtNheight,250); n++;
XtSetArg(wargs[n],XtNwidth, 150); n++;
XtSetValues(toplevel,wargs,n);
form = XtCreateManagedWidget("form",formWidgetClass,
toplevel, NULL, 0);
box1 = XtCreateManagedWidget("box1",boxWidgetClass,
form, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNtop, XtChainTop); n++;
XtSetArg(wargs[n], XtNbottom, XtChainTop); n++;
XtSetValues(box1,wargs,n);
quit1 = quit_button(box1);
box2 = XtCreateManagedWidget("box2",boxWidgetClass,
form, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNfromVert, box1); n++;
XtSetValues(box2,wargs,n);
quit2 = quit_button(box2);
box3 = XtCreateManagedWidget("box3",boxWidgetClass,
form, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNbottom, XtChainBottom); n++;
XtSetArg(wargs[n], XtNtop, XtChainBottom); n++;
XtSetArg(wargs[n], XtNfromVert, box2); n++;
XtSetValues(box3,wargs,n);
quit3 = quit_button(box3);
XtRealizeWidget(toplevel);
XtMainLoop();
}
Dialog Widget
- the dialog widget is basically a form widget that can be used to prompt the user for a
piece of data
- the dialog widget consists of a label, an area where text can be entered and a row for
buttons
- the dialog widget automatically creates the widgets for the label and text entry, the
programmer needs to create the widgets for the buttons, these are assumed to be command
widgets, or a subclass of the command widget class
- there are two dialog widget resources that are of use to use
- the label resource contains the label for the widget, it is displayed at the top of the
dialog widget
- the value resource is the initial value for the text string to be entered by the user,
if a value for this resource isn't specified the user won't be able to enter text in this
instance of the dialog widget
- if the initial text string should be empty then the value "" should be used
for the value resource
- once the user has entered a text string the value of the value resource can be retrieved
using the following convenience function:
String XawDialogGetValueString(w)
Widget w;
- the parameter w is the widget id of the dialog widget, the value of this resource can
also be retrieved using the XtGetValues procedure
- the children that are added to the dialog widget are assumed to be some form of command
widget
- the top, bottom, and fromLeft resources for these widgets are automatically set by the
dialog widget and shouldn't be modified by the programmer
- the following convenience routine can be used to add child widgets to the dialog widget
XawDialogAddButton(w, name, func, client_data)
Widget w;
String name;
XtCallBackProc func;
XtPointer client_data;
- this procedure creates a command widget using the name parameter as the name of the
widget
- the callback procedure for this widget is given by the func parameter, and client_data
is the client data to be sent to this callback procedure
- the first parameter, w, is the widget id for the dialog widget
- all the actions for the dialog widget are normally performed by the command widgets
- for example the dialog widget could ask the user for a file name, command buttons with
the labels "ok" and "cancel" would then be added to this widget
- when the ok button is selected, the string in the dialog widget is retrieved and the
file is processed, and if the cancel button is selected the dialog widget is removed from
the screen
/*****************************************************
*
* composite.c
*
* A very simple X program that shows how the composite
* widgets in the Athena widget set are used
*
* This program constructs a dialog widget that is used
* to enter a name. This widget has three buttons,
* one for accepting the name (printing it), one
* to cancel the current value, and the last one for
* exiting from the program.
*
****************************************************/
#include < X11/StringDefs.h >
#include < X11/Intrinsic.h >
#include < X11/Xaw/Dialog.h >
#include < stdio.h >
void sprint(w,dialog,call)
Widget w;
Widget dialog;
XtPointer call; {
char *s;
s = XawDialogGetValueString(dialog);
printf("%s\n",s);
}
void reset(w,dialog,call)
Widget w;
Widget dialog;
XtPointer call; {
char *s;
Arg wargs[5];
s = (char *)malloc(1);
s[0] = 0;
XtSetArg(wargs[0],XtNvalue,s);
XtSetValues(dialog,wargs,1);
}
void quit(w,dialog,call)
Widget w;
Widget dialog;
XtPointer call; {
exit(0);
}
main(argc,argv)
int argc;
char **argv; {
Widget toplevel;
Widget dialog;
Arg wargs[10];
int n;
toplevel = XtInitialize(argv[0],"simple",NULL, 0,
&argc, argv);
n = 0;
XtSetArg(wargs[n],XtNheight,250); n++;
XtSetArg(wargs[n],XtNwidth, 200); n++;
XtSetValues(toplevel,wargs,n);
dialog = XtCreateManagedWidget("dialog",dialogWidgetClass,
toplevel, NULL, 0);
n=0;
XtSetArg(wargs[n], XtNlabel, "Enter a name"); n++;
XtSetArg(wargs[n], XtNvalue, ""); n++;
XtSetValues(dialog,wargs,n);
XawDialogAddButton(dialog,"accept",sprint,dialog);
XawDialogAddButton(dialog,"cancel",reset,dialog);
XawDialogAddButton(dialog,"quit",quit,dialog);
XtRealizeWidget(toplevel);
XtMainLoop();
}
Go to Simple Widgets
Go to Index
Go to Pixmaps and Bitmaps