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:
    1. the pane must be between its min and max size
    2. do not adjust panes with skipAdjust set
    3. 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();

  }