v01i037: menupane: popup menu program for the X toolkit, Part01/01

Mike Wexler mikew at wyse.wyse.com
Wed Sep 14 06:47:30 AEST 1988


Submitted-by: rlh2 at ukc.ac.uk
Posting-number: Volume 1, Issue 37
Archive-name: menupane/part01

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  Makefile MenuPane.3x MenuPane.c MenuPane.h MenuPaneP.h
#   README TMstate.cdif menutest.c panetest.c patchlevel.h
# Wrapped by mikew at x2 on Tue Sep 13 13:46:24 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(138 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
XOBJS = menutest.o
XCFLAGS=-I/usr/new/usr/include
XXLIBS = -L/usr/new/usr/lib -lXaw -lXt -lX11
X
Xmenutest:	$(OBJS)
X	cc -o $@ $(OBJS) $(XLIBS)
END_OF_Makefile
if test 138 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MenuPane.3x -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MenuPane.3x\"
else
echo shar: Extracting \"MenuPane.3x\" \(4390 characters\)
sed "s/^X//" >MenuPane.3x <<'END_OF_MenuPane.3x'
X.\"
X.\" Add simple keeps to MAN macros so .TS/.TE will work
X.\"
X.de KS	\"	Keep start
X.br
X.in 0
X.di KP
X..
X.de KE	\" 	Keep end
X.br
X.di
X.ne \\n(dnu
X.nr fI \\n(.u
X.nf
X.KP
X.if \\n(fI .fi
X.in
X..
X.TH "MenuPane" 3X
X.na
X.nh
X.SH NAME
XMenuPaneWidgetClass \- An X Widget for creating menu panes.
X.SH SYNOPSIS
X\fB
X.B #include <X11/StringDefs.h>
X.br
X.B #include <X11/Intrinsic.h>
X.br
X.br
X.B #include "MenuPane.h"
X\fR
X.SH CLASSES
XA subclass of Core, Composite and ConstraintClass.
X.P
XThe widget class to use when creating a 
X.I MenuPane\^
Xwidget is \fBmenuPaneWidgetClass\fP.
X.P
XThe class name of 
X.I MenuPane\^
Xis "MenuPane".
X.SH DESCRIPTION
XThe \fIMenuPane\fP provides a convenient method for creating menus. The
X\fIMenuPane\fP looks after its children in either a horizontal or vertical
Xarrangement and resizes its managed children proportionally to the change
Xin its size. A \fIMenuPane\fP will only control children who are in its
Xcurrently managed set. When a child is managed or unmanaged and the
X\fIMenuPane\fP has been realized, its siblings are resized to make room for
Xthe new child or to take up the child's space. The \fIMenuPane\fP never
Xmakes requests to its parent for a change in its geometry and is content
Xwith whatever geometry it is given. \fIMenuPane\fP widgets can be nested
Xto allow for a combination of vertical and horizontal menu layouts in
Xa parent menu. Children of a \fIMenuPane\fP are normally of the \fICommand\fP
Xsubclass, however any class of widget is accepted by a \fIMenuPane\fP.
XChildren of a vertical \fIMenuPane\fP are laid out from top to bottom with
Xtheir borders overlapping. Children of a horizontal \fIMenuPane\fP are laid out
Xfrom side to side with their borders overlapping. Children are laid out in
Xthe order that they were created (by calls to XtCreateWidget). Therefore
Xif a child becomes managed it is placed immeadiately below/to the side of
Xthe sibling that was created before it. The size of a \fIMenuPane\fP
Xdefaults to the size of its parent.
X.SH "NEW RESOURCES"
XTo specify any of these resources within a resource defaults file,
Xsimply drop the \fIXtN\fP prefix from the resource name.
X.I MenuPane\^
Xdefines the following new resources:
X.sp 1
X.KS
X.TS
Xcenter allbox;
XcB sss
XlB lB lB lB
Xllll.
XMenuPane Resource Set
XName	Class	Type	Default
X_
XXtNvertPane	XtCVertpane	Boolean	TRUE
XXtNaskChild	XtCAskchild	Boolean	TRUE
X.TE
X.KE
X.sp 1
X.IP \fBXtNvertPane\fP
XIndicates whether the pane is considered vertical (TRUE) or horizontal
X(FALSE). Vertical panes position their children so that their widths
Xare the same as the pane's width. A child's height is not initially decided by
Xthe pane. Children are laid out top to bottom.
XHorizontal panes position their children so that their heights are the same
Xas the pane's height. A child's width is not initially decided by the pane.
XChildren are laid out side by side.
XThe pane does however control resizing of its children.
X.IP \fBXtNaskChild\fP
XIf TRUE the pane will ask its children their preferred size (using
XXtQueryGeometry) whenever a child becomes managed or unmanaged.
XIf FALSE the pane will assume the childs current size is preferred.
X.SH "CONSTRAINT RESOURCES"
XNo public constraint resources are added by the \fIMenuPane\fP class.
X.bp
X.SH "INHERITED RESOURCES"
XThe following resources are inherited from the named superclasses:
X.sp 1
X.KS
X.TS
Xcenter allbox;
XcB sss
XlB lB lB lB
Xllll.
XCore Resource Set -- CORE(3X)
XName	Class	Type	Default
X_
XXtNscreen	XtCScreen	XScreen *	0
XXtNcolormap	XtCColormap	Pointer	NULL
XXtNancestorSensitive	XtCAncestorSenstitive	Boolean	TRUE
XXtNx	XtCX	int	0
XXtNy	XtCY	int	0
XXtNwidth	XtCWidth	int	10
XXtNheight	XtCHeight	int	10
XXtNdepth	XtCDepth	int	0
XXtNbackground	XtCBackground	Pixel	White
XXtNborderWidth	XtCBorderWidth	int	0
XXtNborder	XtCBorder	Pixel	Black
XXtNsensitive	XtCSensitive	Boolean	TRUE
XXtNmappedWhenManaged	XtCMappedWhenManaged	Boolean	TRUE
XXtNdestroyCallback	XtCCallback	Pointer	NULL
X.TE
X.KE
X.sp 1
X.SH "TRANSLATIONS"
XThere are no default translations in the \fIMenuPane\fP class.
X.SH "ACTIONS"
XThere are no actions added by the \fIMenuPane\fP class.
X.SH AUTHOR
XRichard Hesketh.
X.br
XComputing Lab., University of Kent at Canterbury, UK.
X.SH SEE ALSO
X\fIpanetest\fP - example test program using \fIMenuPane\fP's
X.br
X\fIProgramming With the X Widgets\fP,
X.br
X\fIX Toolkit Intrinsics - C Language X Interface\fP,
X.br
X\fIXlib - C Language Interface, Protocol Version 11\fP.
END_OF_MenuPane.3x
if test 4390 -ne `wc -c <MenuPane.3x`; then
    echo shar: \"MenuPane.3x\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MenuPane.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MenuPane.c\"
else
echo shar: Extracting \"MenuPane.c\" \(11055 characters\)
sed "s/^X//" >MenuPane.c <<'END_OF_MenuPane.c'
X#ifndef lint
Xstatic char rcsid[] = "$Header: MenuPane.c,v 1.2 88/08/23 18:11:05 rlh2 Exp $";
X#endif lint
X
X/**********************************************************************
X *	                	MenuPaneWidget			      *
X *             (c) 1988 Richard Hesketh / rlh2 at ukc.ac.uk              *
X *           Computing Lab. University of Kent at Canterbury          *
X *                                                                    *
X * Subclass of constraintWidgetClass :looks after its children either *
X *                               horizontally or vertically arranged  *
X **********************************************************************
X
X This software is in the Public Domain and as such can be freely copied       
X and distributed provided this notice and the author's name is included.
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <X11/Xos.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include "MenuPaneP.h"
X
X#define CONSTRAINTS_MANAGED(w) (((MPConstraint)w->core.constraints)->menuPane.managed_done)
X
Xstatic void Initialize();
Xstatic void Resize();
Xstatic void Realize();
Xstatic XtGeometryResult Geometry_handler();
Xstatic void Change_managed();
Xstatic XtGeometryResult MenuPane_geometry();
Xstatic void constraint_Initialize();
X
X/*
X * New resources added by this subclass :-
X *
X *  XtNvertPane - if TRUE pane is vertically arranged, FALSE = horizontal.
X *  XtNaskChild - if TRUE the child is asked what size it prefers.
X */
Xstatic XtResource resources[] = {
X	{ XtNvertPane, XtCVertpane, XtRBoolean, sizeof(Boolean),
X		XtOffset(MenuPaneWidget, menuPane.vert_pane), XtRString, "TRUE"},
X	{ XtNaskChild, XtCAskchild, XtRBoolean, sizeof(Boolean),
X		XtOffset(MenuPaneWidget, menuPane.ask_child), XtRString, "TRUE"},
X};
X
XMenuPaneClassRec menuPaneClassRec = {
X  {
X/* core_class fields */	
X    /* superclass	  */	(WidgetClass) &constraintClassRec,
X    /* class_name	  */	"MenuPane",
X    /* widget_size	  */	sizeof(MenuPaneRec),
X    /* class_initialize   */    NULL,
X    /* class_part_initialize */ NULL,
X    /* class_inited       */	FALSE,
X    /* initialize	  */	Initialize,
X    /* initialize_hook	  */	NULL,
X    /* realize		  */	Realize,
X    /* actions		  */	NULL,
X    /* num_actions	  */	0,
X    /* resources	  */	resources,
X    /* num_resources	  */	XtNumber(resources),
X    /* xrm_class	  */	NULLQUARK,
X    /* compress_motion	  */	TRUE,
X    /* compress_exposure  */	TRUE,
X    /* compress_enterleave */	TRUE,
X    /* visible_interest	  */	FALSE,
X    /* destroy		  */	NULL,
X    /* resize		  */	Resize,
X    /* expose		  */	XtInheritExpose,
X    /* set_values	  */	NULL,
X    /* set_values_hook	  */	NULL,
X    /* set_values_almost  */	XtInheritSetValuesAlmost,
X    /* get_values_hook	  */	NULL,
X    /* accept_focus	  */	NULL,
X    /* version		  */	XtVersion,
X    /* callback_private   */	NULL,
X    /* tm_table           */	NULL,
X    /* query_geometry	  */	MenuPane_geometry
X  },
X  {
X/* composite_class fields */
X    /* geometry_handler	  */	Geometry_handler,
X    /* change_managed	  */	Change_managed,
X    /* insert_child	  */	XtInheritInsertChild,
X    /* delete_child	  */	XtInheritDeleteChild,
X    /* move_focus_to_next */	NULL, /* remove these, somebody please! */
X    /* move_focus_to_prev */	NULL
X  },
X  {
X/* constraint_class fields */
X    /* resources          */    NULL,
X    /* num_resources      */    0,
X    /* constraint_size    */    sizeof(MPConstraintRecord),
X    /* initialize         */    constraint_Initialize,
X    /* destroy            */    NULL,
X    /* set_values         */	NULL
X  },
X/* menuPane_class fields (NO NEW ONES) */
X};
X
X/* class record */
X
XWidgetClass menuPaneWidgetClass = (WidgetClass)&menuPaneClassRec;
X
X/****************************************************************
X *
X * Standard Widget Procedures
X *
X ****************************************************************/
X
X#define SIZE(mpw, cw) (mpw->menuPane.vert_pane ? cw->core.height : cw->core.width)
X#define POSITION(mpw, cw) (mpw->menuPane.vert_pane ? cw->core.y : cw->core.x)
X
X/* > Initialize < */
X/* ARGSUSED */
Xstatic void
XInitialize(request, new)
XWidget request, new;
X{
X	MenuPaneWidget mpw = (MenuPaneWidget)new;
X
X	/* inherit our parent's size if we are given one */
X	if (mpw->core.width == 0)
X		mpw->core.width = XtParent(mpw)->core.width;
X
X	if (mpw->core.height == 0)
X		mpw->core.height = XtParent(mpw)->core.height;
X
X	/* save the old size, height or width for use by Resize() */
X	mpw->menuPane.oldsize = SIZE(mpw, mpw);
X}
X
X
X/* ARGSUSED */
Xstatic void
Xconstraint_Initialize(request, new)
XWidget request, new;
X{
X	/* this child has yet to be managed */
X	CONSTRAINTS_MANAGED(new) = FALSE;
X}
X
X
X/*	> Resize <
X * resize any children
X */
Xstatic void Resize(w)
XWidget w;
X{
X	MenuPaneWidget mpw = (MenuPaneWidget) w;
X	int Kids = 0;
X	int inc, bit, offset, round_up;
X
X#ifdef DEBUG
X	printf("Resize(menuPane)\n");
X#endif
X	if (mpw->composite.num_children == 0)
X		return;
X
X	inc = SIZE(mpw, mpw) - mpw->menuPane.oldsize;
X
X	mpw->menuPane.oldsize = SIZE(mpw, mpw);
X
X	/* count the number of currently managed children */
X	for (bit = 0; bit < mpw->composite.num_children; bit++)
X		if (CONSTRAINTS_MANAGED(mpw->composite.children[bit]))
X			Kids++;
X
X	if (Kids == 0)
X		return;
X
X	bit = inc / Kids;		/* amount to resize each child by */
X	round_up = inc - (bit * Kids);	/* whats left after integer division */
X	offset = 0;			/* what to move the children along by */
X
X#ifndef DEBUG
X	if (XtIsRealized(w))
X		XtUnmapWidget(w);
X#endif DEBUG
X
X	/* resize kids */
X	for (Kids = 0; Kids < mpw->composite.num_children; Kids++)
X	{
X		Widget kw = mpw->composite.children[Kids];
X
X		if (!CONSTRAINTS_MANAGED(kw))
X		{
X			if (mpw->menuPane.vert_pane)
X				XtResizeWidget(kw, mpw->core.width, kw->core.height,
X							kw->core.border_width);
X			else
X				XtResizeWidget(kw, kw->core.width, mpw->core.height,
X							kw->core.border_width);
X			continue;
X		}
X
X		if (mpw->menuPane.vert_pane)
X		{
X			XtResizeWidget(kw, mpw->core.width,
X				kw->core.height + round_up + bit,
X				kw->core.border_width); 
X			XtMoveWidget(kw, kw->core.x, kw->core.y + offset);
X		}
X		else
X		{
X			XtResizeWidget(kw,
X				kw->core.width + round_up + bit,
X				mpw->core.height,
X				kw->core.border_width);
X			XtMoveWidget(kw, kw->core.x + offset, kw->core.y);
X		}
X
X		offset += round_up + bit;
X		round_up = 0;
X	};
X
X#ifndef DEBUG
X	if (XtIsRealized(w))
X		XtMapWidget(w);
X#endif DEBUG
X}
X
X
Xstatic void Realize(w, valueMask, attributes)
XWidget w;
XXtValueMask *valueMask;
XXSetWindowAttributes *attributes;
X{
X	XtCreateWindow(w, InputOutput, (Visual *)CopyFromParent, (XtValueMask)*valueMask, attributes);
X}
X
X
X/* ARGSUSED */
Xstatic XtGeometryResult Geometry_handler(w, request, reply)
XWidget w;
XXtWidgetGeometry *request;
XXtWidgetGeometry *reply;
X{
X	/* Any requests by the children are just refused, the parent
X	 * knows best.
X	 * If the resource XtNaskChild is set to TRUE then when a
X	 * `change managed' event occurs the children are asked their preferred
X	 * size.
X	 */
X	return(XtGeometryNo);
X}
X
X
Xstatic int preferred_size(mpw, use_constraints)
XMenuPaneWidget mpw;
XBoolean use_constraints;
X{
X	Widget cw = NULL;
X	int managed_size = 0;
X	Boolean is_managed;
X	Cardinal i;
X
X	/* calculate the total height or width of the children */
X	for (i = 0; i < mpw->composite.num_children; i++)
X	{
X		is_managed = use_constraints ?
X				CONSTRAINTS_MANAGED(mpw->composite.children[i])
X			        : XtIsManaged(mpw->composite.children[i]);	
X
X		if (is_managed)
X		{
X			cw = mpw->composite.children[i];
X			managed_size += SIZE(mpw, cw) + cw->core.border_width;
X		}
X	}
X
X	if ((managed_size == 0) || (cw == NULL))
X		return (0);
X
X	/* remove the last child's border width */
X	managed_size -= cw->core.border_width;
X	return (managed_size);
X}
X
X
Xstatic int
Xget_prev_pos(w, mpw)
XWidget w;
XMenuPaneWidget mpw;
X{
X	XtWidgetGeometry preferred_return;
X
X	if (mpw->menuPane.ask_child)
X	{
X		(void)XtQueryGeometry(w, (XtWidgetGeometry *)NULL,
X							&preferred_return);
X
X		if (mpw->menuPane.vert_pane)
X			return (preferred_return.height);
X		else
X			return (preferred_return.width);
X	}
X	return (SIZE(mpw, w));
X}
X
X
Xstatic void Change_managed(w)
XWidget w;
X{
X	MenuPaneWidget mpw = (MenuPaneWidget)w;
X	Cardinal i;
X	Widget cw = NULL;
X	int old_size = 0, new_size = 0, prev_pos = 0;
X
X#ifdef DEBUG
X	printf("Change_managed(menuPane, %s)\n",w->core.name);
X#endif
X
X	old_size = preferred_size(mpw, TRUE);
X	new_size = preferred_size(mpw, FALSE);
X
X	/* change the space of the currently managed children to make
X	 * room for the newly managed ones.
X	 */
X	if (old_size > 0 && old_size < new_size)
X	{
X		mpw->menuPane.oldsize = new_size;
X		Resize(w);
X	}
X
X	prev_pos = - mpw->composite.children[0]->core.border_width;
X
X	/* Move children to their right places.
X	 * Children are placed one after the other, down or across,
X	 * in the order that they we created. Their borders are overlapped
X	 * so that only one border width separates two menu elements.
X	 */
X	for (i = 0; i < mpw->composite.num_children; i++)
X	{
X		cw = mpw->composite.children[i];
X
X		if (XtIsManaged(cw))
X		{
X			if (mpw->menuPane.vert_pane)
X				XtMoveWidget(cw, -(cw->core.border_width),
X								    prev_pos);
X			else
X				XtMoveWidget(cw, prev_pos,
X						     -(cw->core.border_width));
X
X			prev_pos += get_prev_pos(cw, mpw) 
X							+ cw->core.border_width;
X			CONSTRAINTS_MANAGED(cw) = TRUE;
X		}
X		else
X			CONSTRAINTS_MANAGED(cw) = FALSE;
X	}
X
X
X	/* change the size of the currently managed children and make
X	 * use up the space of the now unmanaged children.
X	 */
X	if (old_size > 0 && old_size > new_size)
X	{
X		mpw->menuPane.oldsize = new_size;
X		Resize(w);
X	}
X
X	/* if the combined size of the children are smaller or larger than
X	 * the menuPane parent then enlarge or shrink all the children to
X	 * fit. We do this by faking a Resize event.
X	 */
X	new_size = preferred_size(mpw, TRUE);
X	if (SIZE(mpw, mpw) != new_size)
X	{
X		mpw->menuPane.oldsize = new_size;
X		Resize(w);
X	}
X}
X
X
X/* > MenuPane_geometry <
X * return the preferred geometry for the menuPane widget
X * The preferred geometry is the width/height of the menuPane and
X * the combined height/width of the children.
X */
Xstatic XtGeometryResult MenuPane_geometry(w, request, preferred_return)
XWidget w;
XXtWidgetGeometry *request;
XXtWidgetGeometry *preferred_return;
X{
X	MenuPaneWidget mpw = (MenuPaneWidget)w;
X
X	preferred_return->request_mode = CWWidth | CWHeight;
X
X	if (mpw->menuPane.vert_pane)
X	{
X		preferred_return->height = preferred_size(mpw);
X		preferred_return->width = mpw->core.width;
X	}
X	else
X	{
X		preferred_return->height = mpw->core.height;
X		preferred_return->width = preferred_size(mpw);
X	}
X
X	/* the size given the caller is not exactly what we want */
X	if (((request->request_mode & CWWidth) &&
X	   (request->width != preferred_return->width)) ||
X	   ((request->request_mode & CWHeight) &&
X	   (request->height != preferred_return->height)) ||
X	   (preferred_return->request_mode != request->request_mode))
X		return (XtGeometryAlmost);
X
X	/* we are already the perfect size */
X	if ((mpw->core.height == preferred_return->height) &&
X	    (mpw->core.width == preferred_return->width))
X		return (XtGeometryNo);
X
X	return (XtGeometryYes);
X}
END_OF_MenuPane.c
if test 11055 -ne `wc -c <MenuPane.c`; then
    echo shar: \"MenuPane.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MenuPane.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MenuPane.h\"
else
echo shar: Extracting \"MenuPane.h\" \(1270 characters\)
sed "s/^X//" >MenuPane.h <<'END_OF_MenuPane.h'
X/*
X * $Header: MenuPane.h,v 1.2 88/08/23 18:11:18 rlh2 Exp $
X */
X
X/**********************************************************************
X *	                	MenuPaneWidget			      *
X *             (c) 1988 Richard Hesketh / rlh2 at ukc.ac.uk              *
X *           Computing Lab. University of Kent at Canterbury          *
X *                                                                    *
X * Subclass of constraintWidgetClass :looks after its children either *
X *                               horizontally or vertically arranged  *
X **********************************************************************
X
X This software is in the Public Domain and as such can be freely copied       
X and distributed provided this notice and the author's name is included.
X*/
X
X#ifndef _XtMenuPaneH_h
X#define _XtMenuPaneH_h
X/*
X * New Resources/Parameters :
X */ 
X
X#define XtNvertPane	"vertPane"
X#define XtNaskChild	"askChild"
X
X#define XtCVertpane	"Vertpane"
X#define XtCAskchild	"Askchild"
X
X/* Class record pointer */
X
Xextern WidgetClass	menuPaneWidgetClass;
X
X/* Widget Type definition */
X
Xtypedef	struct	_MenuPaneRec	*MenuPaneWidget;
Xtypedef struct _MenuPaneClassRec	*MenuPaneWidgetClass;
X
X/*** PUBLIC ROUTINES defined in MenuPane Widget ***/
X/* NONE */
X
X#endif _XtMenuPaneH_h
END_OF_MenuPane.h
if test 1270 -ne `wc -c <MenuPane.h`; then
    echo shar: \"MenuPane.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MenuPaneP.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MenuPaneP.h\"
else
echo shar: Extracting \"MenuPaneP.h\" \(1957 characters\)
sed "s/^X//" >MenuPaneP.h <<'END_OF_MenuPaneP.h'
X/*
X * $Header: MenuPaneP.h,v 1.2 88/08/23 18:10:46 rlh2 Exp $
X */
X
X/**********************************************************************
X *	                	MenuPaneWidget			      *
X *             (c) 1988 Richard Hesketh / rlh2 at ukc.ac.uk              *
X *           Computing Lab. University of Kent at Canterbury          *
X *                                                                    *
X * Subclass of constraintWidgetClass :looks after its children either *
X *                               horizontally or vertically arranged  *
X **********************************************************************
X
X This software is in the Public Domain and as such can be freely copied       
X and distributed provided this notice and the author's name is included.
X*/
X
X#ifndef	_XtMenuPanePrivate_h
X#define _XtMenuPanePrivate_h
X
X#include "MenuPane.h"
X
Xstruct _mpconstraintpart {
X	Boolean         managed_done;
X};
X
Xtypedef struct _mpconstraintpart MPConstraintPart;
X
Xstruct _mpconstraintrec {
X	MPConstraintPart menuPane;
X};
X
Xtypedef struct _mpconstraintrec MPConstraintRecord;
Xtypedef MPConstraintRecord *MPConstraint;
X
X
Xtypedef struct _menuPaneclasspart {
X	int	mumble; /* no new fields */
X} MenuPaneClassPart;
X
X/* Full Class Record declaration */
X
Xtypedef struct	_MenuPaneClassRec {
X	CoreClassPart		core_class;
X	CompositeClassPart	composite_class;
X	ConstraintClassPart	constraint_class;
X	MenuPaneClassPart	menuPane_class;
X} MenuPaneClassRec;
X
X/* Class record variable */
X
Xextern MenuPaneClassRec	menuPaneClassRec;
X
Xstruct _menuPanepart {
X	/* settable resources */
X	Boolean	vert_pane;	/* TRUE if menu pane is vertical */
X	Boolean	ask_child;	/* TRUE if child is asked its prefered size */
X
X	/* data derived from resources */
X	int	oldsize;
X};
X	
Xtypedef struct _menuPanepart MenuPanePart;
X
Xtypedef struct _MenuPaneRec {
X	CorePart	core;
X	CompositePart	composite;
X	ConstraintPart	constraint;
X	MenuPanePart	menuPane;
X} MenuPaneRec;
X
X#endif	_XtMenuPanePrivate_h
END_OF_MenuPaneP.h
if test 1957 -ne `wc -c <MenuPaneP.h`; then
    echo shar: \"MenuPaneP.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(1378 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThere has been a few articles recently wondering about popup shells, menus
Xand grabs. Well, I enclose a short test program which implements a popup
Xmenu in the toolkit. The program will work as is on a VAX. However on a SUN
Xdue to a bug in XtConvertStringToBoolean() in TMstate.c, it fails to pop
Xdown the popup menu when the button is released. This problem can be fixed
Xwith the context diff given in the enclosed file: TMstate.cdif
X
XAfter you have applied this patch the MenuPopup action will set the grab
Xproperly so that all events will be propagated to the last spring loaded
Xshell as well as the widget that they happened in.
X
XNow back to the example program. The program creates a single command button
Xwithin a form. The translations of this button are set so that when the
Xleft mouse button is pressed a shell widget is positioned relative
Xto the button. This shell is then popped up revealing a menu of 4 command
Xbuttons. With the left mouse button held down any of the 4 buttons can be
Xchosen by moving in to them (this sets them in the foreground colour).
XIf the button is released when it is inside any of the 4 menu buttons then
Xthe callback of that particular button is called. The menu is then popped
Xdown. If the button is released outside of any of the menu buttons then
Xno callback is called and the menu is just popped down.
X
XRichard Hesketh
Xrlh2 at ukc.ac.uk
END_OF_README
if test 1378 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f TMstate.cdif -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"TMstate.cdif\"
else
echo shar: Extracting \"TMstate.cdif\" \(507 characters\)
sed "s/^X//" >TMstate.cdif <<'END_OF_TMstate.cdif'
X*** ORIG/TMstate.c	Fri Feb 26 17:48:55 1988
X--- TMstate.c	Sat Aug 27 16:46:45 1988
X***************
X*** 1192,1198 ****
X      XtConvert((Widget) NULL, XtRString, &fromVal, XtRBoolean, &toVal);
X      if (toVal.addr == NULL) return FALSE;
X  
X!     *bP = (Boolean) *(int *)toVal.addr;
X  
X      return TRUE;
X  }
X--- 1305,1311 ----
X      XtConvert((Widget) NULL, XtRString, &fromVal, XtRBoolean, &toVal);
X      if (toVal.addr == NULL) return FALSE;
X  
X!     *bP = *(Boolean *)toVal.addr;
X  
X      return TRUE;
X  }
END_OF_TMstate.cdif
if test 507 -ne `wc -c <TMstate.cdif`; then
    echo shar: \"TMstate.cdif\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f menutest.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"menutest.c\"
else
echo shar: Extracting \"menutest.c\" \(6741 characters\)
sed "s/^X//" >menutest.c <<'END_OF_menutest.c'
X/*******************************************************************************
X * Very simple test program to show how popup menus are created in the toolkit *
X *                   Richard Hesketh     email: rlh2 at ukc.ac.uk                 *
X *               Computing Lab. University of Kent at Canterbury, UK           *
X *									       *
X *       Permission to use, copy, modify, and distribute this program and      *
X * any documentation for any purpose and without fee is granted provided that  *
X * the authors name and this notice appears in all copies. The author accepts  *
X * no responsibility for the use of this program.                              *
X *******************************************************************************/
X 
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Command.h>
X#include <X11/Form.h>
X#include <X11/Shell.h>
X
X/* forward references to procedures */
Xvoid do_system();
Xvoid quit();
Xvoid set_popup();
X
X/* widget hierarchy */
XWidget	toplevel;
XWidget		 layout;
XWidget			pb1;	/* button who popups up the menu when pressed */
X
XWidget			popup_shell;		  /* shell of popup menu */
XWidget				pop_layout;	  /* form widget of popup menu */
XWidget					erik[4];  /* menu buttons */
X
X/* translations for the button to popup the menu
X * set_popup positions the shell.
X * MenuPopup realizes the shell.
X */
Xstatic String pb_Trans =
X	"<EnterWindow>:	highlight() \n\
X	 <LeaveWindow>: unhighlight() \n\
X	 <Btn1Down>:	set_popup(%s) MenuPopup(%s)";
X
X/* translations for the command buttons of the popup menu
X * the command callback is invoked when the button is released with
X * the pointer in the command widget.
X */
Xstatic String cb_Trans =
X	"<EnterWindow>:	set() \n\
X	 <LeaveWindow>: unset() \n\
X	 <Btn1Up>:	notify()";
X
X/* translations for the shell of the popup menu.
X * when the button is released the shell catches it and pops itself down.
X */
Xstatic String pm_Trans =
X	"<Btn1Up>:	MenuPopdown()";
X
X/* new actions added by this program */
Xstatic XtActionsRec menu_actions[] = {
X	{ "set_popup",	set_popup },
X};
X
X/* application routines !! */
Xstatic XtCallbackRec b_callbacks[] = {
X	{ do_system, (caddr_t)NULL },
X	{ (XtCallbackProc)NULL, (caddr_t)NULL }
X};
X
X/* name of the shell, used by set_popup and MenuPopup actions */
Xstatic String popup_menu_name = "popup_menu";
X
Xvoid
Xmain(argc, argv)
Xunsigned int argc;
Xchar **argv;
X{
X	Arg args[6];
X	Cardinal i = 0;
X	char ptrans[250];
X
X	/* initialize the toolkit and register the actions */
X	i = 0;
X	toplevel = XtInitialize( "ademo", "Xademo", (ArgList)args, i, &argc, argv );
X	XtSetArg(args[i], XtNwidth, 200); i++;
X	XtSetArg(args[i], XtNheight, 30); i++;
X	XtSetValues(toplevel, (ArgList)args, i);
X
X	XtAddActions((XtActionList)menu_actions, XtNumber(menu_actions));
X
X	/* create the top button and its form parent */
X	i = 0;
X	layout = XtCreateManagedWidget("layout", formWidgetClass, toplevel,
X								(ArgList)args, i);
X
X	/* create the translations for the button which pops up the menu */
X	/* we pass the name of the popup menu to both set_popup and MenuPopup */
X	(void)sprintf(ptrans, pb_Trans, popup_menu_name, popup_menu_name);
X	i = 0;
X	XtSetArg(args[i], XtNwidth, 200); i++;
X	XtSetArg(args[i], XtNheight, 30); i++;
X	XtSetArg(args[i], XtNtranslations, XtParseTranslationTable(ptrans)); i++;
X	pb1 = XtCreateManagedWidget("button_to_popup_menu", commandWidgetClass,
X							layout, (ArgList)args, i);
X
X	/* create the popup menu ... its shell, its layout widget and the menu
X	 * buttons it holds.
X	 */
X	i = 0;
X	XtSetArg(args[i], XtNtranslations, XtParseTranslationTable(pm_Trans)); i++;
X	popup_shell = XtCreatePopupShell("popup_menu", overrideShellWidgetClass,
X							pb1, (ArgList)args, i);
X
X	i = 0;
X	pop_layout = XtCreateManagedWidget("layout", formWidgetClass, popup_shell,
X								(ArgList)args, i);
X
X	i = 0;
X	XtSetArg(args[i], XtNwidth, 110); i++;
X	XtSetArg(args[i], XtNheight, 29); i++;
X
X	/* set the translations for the buttons of the menu.
X	 * Set on window entry. Unset on window leave.
X	 * Call the callback when button 1 is released.
X	 */
X	XtSetArg(args[i], XtNtranslations, XtParseTranslationTable(cb_Trans)); i++;
X	XtSetArg(args[i], XtNcallback, b_callbacks); i++;
X
X	/* this button will give a listing of the current directory */
X	XtSetArg(args[i], XtNlabel, "ls -la"); i++;
X	erik[0] = XtCreateManagedWidget("first_button", commandWidgetClass,
X						pop_layout, (ArgList)args, i);
X
X	i = 6;
X	/* this button will print the name of the current directory */
X	XtSetArg(args[4], XtNlabel, "pwd");
X	XtSetArg(args[5], XtNfromVert, erik[0]);
X	erik[1] = XtCreateManagedWidget("second_button", commandWidgetClass,
X						pop_layout, (ArgList)args, i);
X
X	i = 6;
X	/* this button will print `hello' */
X	XtSetArg(args[4], XtNlabel, "echo \"hello\"");
X	XtSetArg(args[5], XtNfromVert, erik[1]);
X	erik[2] = XtCreateManagedWidget("third_button", commandWidgetClass,
X						pop_layout, (ArgList)args, i);
X
X	i = 5;
X	/* this button quits the test program */
X	XtSetArg(args[4], XtNlabel, "QUIT");
X	XtSetArg(args[3], XtNfromVert, erik[2]);
X	erik[3] = XtCreateManagedWidget("fourth_button", commandWidgetClass,
X						pop_layout, (ArgList)args, i);
X	XtAddCallback(erik[3], XtNcallback, (caddr_t)quit);
X
X	XtRealizeWidget(toplevel);
X	XtMainLoop();
X}
X
X
X/* ARGSUSED */
Xvoid
Xdo_system(w, client_data, call_data)
XWidget w;
Xcaddr_t client_data, call_data; /* unused */
X{
X	String func_name;
X	Arg args[1];
X
X	/* simple application ... do the U*IX command named in the widget's label */
X	XtSetArg(args[0], XtNlabel, &func_name);
X	XtGetValues(w, (ArgList)args, 1);
X
X	system(func_name);
X}
X
X
X/* ARGSUSED */
Xvoid
Xquit(w, client_data, call_data)
XWidget w;			/* unused */
Xcaddr_t client_data, call_data; /* unused */
X{
X	exit(0);
X}
X
X
XWidget
Xget_shell_from_name(name)
XString name;
X{
X	if (strcmp(name, popup_menu_name) == 0)
X		return (popup_shell);
X	else
X		return (NULL);
X}
X
X
X/* ARGSUSED */
Xvoid
Xset_popup(w, event, params, num_params)
XWidget w;
XXEvent *event; /* unused */
XString *params;
XCardinal *num_params;
X{
X	/* position the menu, whose name was passed as the first and only
X	 * parameter at position (20,5) relative to the Widget w.
X	 */
X	Widget a_shell;
X	int x, y;
X	Arg args[2];
X
X	if (*num_params != 1)
X		XtError("Wrong parameter count passed to set_popup()");
X
X	/* get the internal Widget id of the named shell */
X	a_shell = get_shell_from_name(params[0]);
X
X	if (a_shell == NULL)
X		XtError("Wrong shell name passed to set_popup()");
X
X	XtTranslateCoords(w, (Position)20, (Position)5, &x, &y);
X
X#ifndef SHELL_BUG_FIX
X	/* currently this is the only way to move created shells */
X	XtMoveWidget(a_shell, x, y);
X#else
X	/* use this when R3 fixes the shell bug */
X	XtSetArg(args[0], XtNx, x);
X	XtSetArg(args[1], XtNy, y);
X	XtSetValues(a_shell, (ArgList)args, 2);
X#endif SHELL_BUG_FIX
X}
END_OF_menutest.c
if test 6741 -ne `wc -c <menutest.c`; then
    echo shar: \"menutest.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f panetest.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"panetest.c\"
else
echo shar: Extracting \"panetest.c\" \(2306 characters\)
sed "s/^X//" >panetest.c <<'END_OF_panetest.c'
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Command.h>
X#include "MenuPane.h"
X
XWidget toplevel, layout, fred[5], mPane1, erik[3], mPane2, john;
X
Xunmanage()
X{
X	XtUnmanageChild(mPane2);
X}
X
Xmanage()
X{
X	XtManageChild(mPane2);
X}
X
Xvoid main(argc, argv)
X    unsigned int argc;
X    char **argv;
X{
X	Arg args[4];
X	Cardinal i = 0;
X
X	i = 0;
X	toplevel = XtInitialize( "ademo", "Xademo", (ArgList)args, i, &argc, argv );
X	XtSetArg(args[i], XtNwidth, 300); i++;
X	XtSetArg(args[i], XtNheight, 100); i++;
X	XtSetValues(toplevel, (ArgList)args, i);
X
X	i = 0;
X	XtSetArg(args[i], XtNvertPane, FALSE); i++;
X
X	layout = XtCreateManagedWidget("layout", menuPaneWidgetClass, toplevel, (ArgList)args, i);
X
X	/* create a vertical pane with 5 children */
X	i = 0;
X	XtSetArg(args[i], XtNwidth, 70); i++;
X	XtSetArg(args[i], XtNheight, 50); i++;
X	XtSetArg(args[i], XtNvertPane, TRUE); i++;
X
X	mPane1 = XtCreateManagedWidget("MenuPane1", menuPaneWidgetClass, layout, (ArgList)args, i);
X
X	i = 0;
X	fred[0] = XtCreateManagedWidget("A", commandWidgetClass, mPane1, (ArgList)args, i);
X	fred[1] = XtCreateManagedWidget("B", commandWidgetClass, mPane1, (ArgList)args, i);
X	fred[2] = XtCreateManagedWidget("C", commandWidgetClass, mPane1, (ArgList)args, i);
X	fred[3] = XtCreateManagedWidget("D", commandWidgetClass, mPane1, (ArgList)args, i);
X	fred[4] = XtCreateManagedWidget("E", commandWidgetClass, mPane1, (ArgList)args, i);
X
X	/* create a horizontal pane with 3 children */
X	i = 0;
X	XtSetArg(args[i], XtNwidth, 70); i++;
X	XtSetArg(args[i], XtNheight, 50); i++;
X	XtSetArg(args[i], XtNvertPane, FALSE); i++;
X
X	mPane2 = XtCreateManagedWidget("MenuPane2", menuPaneWidgetClass, layout, (ArgList)args, i);
X
X	i = 0;
X	erik[0] = XtCreateManagedWidget("1", commandWidgetClass, mPane2, (ArgList)args, i);
X	erik[1] = XtCreateManagedWidget("2", commandWidgetClass, mPane2, (ArgList)args, i);
X	erik[2] = XtCreateManagedWidget("3", commandWidgetClass, mPane2, (ArgList)args, i);
X
X	i = 0;
X	john = XtCreateManagedWidget("A Pane Button", commandWidgetClass, layout, (ArgList)args, i);
X
X	/* press "1" and see what happens */
X	XtAddCallback(erik[0], XtNcallback, unmanage, (caddr_t)NULL);
X
X	/* press "A Pane Button" and see what happens */
X	XtAddCallback(john, XtNcallback, manage, (caddr_t)NULL);
X
X	XtRealizeWidget(toplevel);
X	XtMainLoop();
X}
END_OF_panetest.c
if test 2306 -ne `wc -c <panetest.c`; then
    echo shar: \"panetest.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f patchlevel.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"patchlevel.h\"
else
echo shar: Extracting \"patchlevel.h\" \(21 characters\)
sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
X#define PATCHLEVEL 0
END_OF_patchlevel.h
if test 21 -ne `wc -c <patchlevel.h`; then
    echo shar: \"patchlevel.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 1 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330



More information about the Comp.sources.x mailing list