[comp.sys.hp] Picking from Device Independent Starbase Display List

neil@yc.estec.nl (Neil Dixon) (02/12/90)

Some months ago I inquired about the correct method of picking from a
device independent display list in SBDL, in this newsgroup. Since
there is no equivalent of `pick_from_segment' for device independent
display lists in SBDL, the answer appears to be that the programmer
must perform his/her own traversal of the display list, looking for a
hit after each `display_element' call.

If somebody already has the code to do this sort of thing, could they
send it to me, before I go ahead and implent it myself. At first
glance it looks like a very messy thing to have to do.

I also see no reason why HP have not implemented this type of thing in
SBDL (other than for PHIGS compatibility?), since I've discovered at
least one situation in which it's virtually vital for this
functionality to exist; namely when running an SBDL application in an
X window. When running an application under X, it's necessary to be
able to handle resizeing of the window containing the graphics. In
this case you normally need to redraw whatever graphics are displayed
in the new sized window. The only way Starbase can see this change in
size is for the user to reopen the graphics window with a call to
`gopen'. However, if you are using a device dependent display list,
the display list is destroyed by the gopen call (or is this a bug?)
and this then has to be regenerated, which may well be a non-trivial task.
The most efficient solution is to use a device independent display
list, but if the application is required to perform picking on the
resulting graphics output, then the above described functionality is required.

Is there anybody at HP prepared to comment on my suggestions; refute
my arguments; give me a better solution; etc...
-- 
Neil Dixon <neil@yc.estec.nl> UUCP:...!mcvax!esatst!neil, BITNET: NDIXON@ESTEC
Thermal Control & Life Support Division (YC) 
European Space Research and Technology Centre (ESTEC),
Noordwijk, The Netherlands.

stroyan@hpfcso.HP.COM (Mike Stroyan) (02/13/90)

> Some months ago I inquired about the correct method of picking from a
> device independent display list in SBDL, in this newsgroup. Since
> there is no equivalent of `pick_from_segment' for device independent
> display lists in SBDL, the answer appears to be that the programmer
> must perform his/her own traversal of the display list, looking for a
> hit after each `display_element' call.

You can use pick_from_segment with a device independent display list.
It may not perform as well as a device dependent display list because
the transformation and clipping will be done by the CPU rather than any
graphics accelerator box you are using.  There is no pick_from_segment
equivalent that uses a second file descriptor to do the hit checks.

> I also see no reason why HP have not implemented this type of thing in
> SBDL (other than for PHIGS compatibility?), since I've discovered at
> least one situation in which it's virtually vital for this
> functionality to exist; namely when running an SBDL application in an
> X window. When running an application under X, it's necessary to be
> able to handle resizeing of the window containing the graphics. In
> this case you normally need to redraw whatever graphics are displayed
> in the new sized window. The only way Starbase can see this change in
> size is for the user to reopen the graphics window with a call to
> `gopen'. However, if you are using a device dependent display list,
> the display list is destroyed by the gopen call (or is this a bug?)
                                         No, it's intentional.
> and this then has to be regenerated, which may well be a non-trivial task.
> The most efficient solution is to use a device independent display
> list, but if the application is required to perform picking on the
> resulting graphics output, then the above described functionality is required.

> Is there anybody at HP prepared to comment on my suggestions; refute
> my arguments; give me a better solution; etc...
> -- 
> Neil Dixon <neil@yc.estec.nl> UUCP:...!mcvax!esatst!neil

If you had to regenerate a device dependent display list for faster
picking, you could use a series of display_segment calls to copy a
device independent display list to open segments in a device dependent
display list.  It would be simple, but rather slow and quite wasteful of
memory.

Actually, you do not need to close a graphics descriptor to react to
an X window resize.  You can use set_p1_p2 to scale the graphics to a
area smaller than the original window open size.  The example program
below creates a large window in a motif DrawingArea widget, gopen's
the window, then scales down the window and set_p1_p2 area.  Since
the parent window is always of a normal size, the momentarily large
graphics window never appears to be very large.

Warning- you probably don't want to ask for backing store in the
graphics window until it is scaled down to a reasonable size.

Mike Stroyan, stroyan@hpfcla.hp.com

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Mike Stroyan <stroyan@hpstryn> on Mon Feb 12 17:33:48 1990
#
# This archive contains:
#	DRawingArea	Makefile	drawing_area.c	
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - DRawingArea
cat >DRawingArea <<'@EOF'
*geometry:            300x300-10+10
*topShadowColor:      #7197e5
*bottomShadowColor:   #36486e
*foreground:          black
*background:          steel blue
*Starbase.background: black
@EOF

chmod 664 DRawingArea

echo x - Makefile
cat >Makefile <<'@EOF'
SHELL=/bin/sh

CFLAGS= -g

X11LIBS= -lXhp11 -lX11
XTKLIBS= -lXw -lXtR2
XTKLIBS= -lXm -lXt
SBLIBS= -ldd98550 -lXwindow -lsb1 -lsb2
SBLIBS= -lddsox11 -lsb1 -lsb2
LPATH=LPATH="/lib:/usr/lib"
LDFLAGS= $(SBLIBS) $(XTKLIBS) $(X11LIBS) -lm -lmalloc

default: drawing_area

# These rules have to be spelled out to put the library "flags" after
# the source file.

.SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~ .p .p~ .g

.c:
	$(LPATH) $(CC) -o $* $< $(CFLAGS) $(LDFLAGS)
@EOF

chmod 644 Makefile

echo x - drawing_area.c
cat >drawing_area.c <<'@EOF'
#include <stdio.h>
#include <starbase.c.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/Frame.h>
#include <Xm/DrawingA.h>

static int display = -1;

redraw()
{
	clear_view_surface(display);
	fill_color(display, 0.3, 0.5, 0.2);
	ellipse(display, 0.3, 0.4, 0.5, 0.5, 0.7);
	flush_buffer(display);
}

void quit(widget, client_data, call_data)
Widget    widget;
caddr_t   client_data;
caddr_t   call_data;
{
	if (display != -1)
		gclose(display);
	exit(0);
}

#define SIZE 2048

void expose(widget, client_data, call_data)
Widget    widget;
caddr_t   client_data;
XmDrawingAreaCallbackStruct *call_data;
{
	Arg arg[10];
	int n;
	Dimension width, height;

	if (XtWindow(widget) == NULL)
		return;

	/* Wait for the last expose event in this group */
	if (call_data->event->xexpose.count != 0)
		return;

	if (display == -1) {
		int temp;

		/* Call gopen with the window at it's original largest size. */
		temp = gopen(
			make_X11_gopen_string(XtDisplay(widget), XtWindow(widget)),
			OUTDEV, "sox11", 0);

		/* Allow the DrawingArea widget to resize.
		 * The client_data parameter contains the address of the
		 * DrawingArea or Frame widget which should be made resizable
		 * now that the gopen has completed.
		 */
		n = 0;
		XtSetArg(arg[n], XmNresizable, True); n++;
		XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
		XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
		XtSetValues(*((Widget *) client_data), arg, n);

		/* Now tell resize callback that the display is ready. */
		display = temp;

		/* Find the size to draw the image for the first time. */
		n = 0;
		XtSetArg(arg[n], XmNwidth, &width); n++;
		XtSetArg(arg[n], XmNheight, &height); n++;
		XtGetValues(widget, arg, n);
		if (width > SIZE) width = SIZE;
		if (height > SIZE) height = SIZE;
		set_p1_p2(display, FRACTIONAL, 0.0, 1.0-height/(double)SIZE, 0.0,
			width/(double)SIZE, 1.0, 1.0);
	}

	redraw();
}

void resize(widget, client_data, call_data)
Widget    widget;
caddr_t   client_data;
caddr_t   call_data;
{
	Arg arg[10];
	int	n;
	Dimension width, height;

	if (XtWindow(widget) == NULL)
		return;

	if (display == -1)
		return;

	/* Sync out the resize before reading the new size. */
	XSync(XtDisplay(widget), 0);

	n = 0;
	XtSetArg(arg[n], XmNwidth, &width); n++;
	XtSetArg(arg[n], XmNheight, &height); n++;
	XtGetValues(widget, arg, n);
	if (width > SIZE) width = SIZE;
	if (height > SIZE) height = SIZE;
	set_p1_p2(display, FRACTIONAL, 0.0, 1.0-height/(double)SIZE, 0.0,
		width/(double)SIZE, 1.0, 1.0);

	redraw();
}

void drawing_area_input(widget, client_data, call_data)
Widget widget;
caddr_t client_data;
XmDrawingAreaCallbackStruct *call_data;
{
	int valid;
	float x, y, z;
	register XEvent *event = call_data->event;

	printf("Received input callback\n");
	if (display == -1)
		return;

	dc_to_vdc(display, event->xbutton.x, event->xbutton.y, 0, &x, &y, &z);
	printf("VDC coordinates are %f, %f, %f\n", x, y, z);
}

main(argc, argv)
int argc;
char *argv[];
{
	Widget toplevel, outer, quit_button, frame, drawing_area;
	Arg arg[15];
	int	n;

	toplevel = XtInitialize("main", "DRawingArea", NULL, 0, &argc, argv);
	if (argc != 1) {
		fprintf(stderr, "Usage mistake\n");
		exit(1);
	}

	n = 0;
	outer = XtCreateManagedWidget(NULL, xmFormWidgetClass, toplevel, arg, n);

	n = 0;
	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
	XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
	XtSetArg(arg[n], XmNlabelString,
		XmStringCreate("Quit", XmSTRING_DEFAULT_CHARSET)); n++;
	quit_button = XtCreateManagedWidget("quit", xmPushButtonWidgetClass,
		outer, arg, n);
	XtAddCallback(quit_button, XmNactivateCallback, quit, NULL);

	n = 0;
	XtSetArg(arg[n], XmNtopWidget, quit_button); n++;
	XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
	XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
	XtSetArg(arg[n], XmNshadowThickness, 5); n++;
	XtSetArg(arg[n], XmNresizable, False); n++;
	frame = XtCreateManagedWidget("Starbase", xmFrameWidgetClass,
	    outer, arg, n);

	n = 0;
	XtSetArg(arg[n], XmNwidth, SIZE); n++;
	XtSetArg(arg[n], XmNheight, SIZE); n++;
	drawing_area = XtCreateManagedWidget("Starbase", xmDrawingAreaWidgetClass,
	    frame, arg, n);
	XtAddCallback(drawing_area, XmNexposeCallback, expose, (caddr_t) &frame);
	XtAddCallback(drawing_area, XmNresizeCallback, resize, drawing_area);
	XtAddCallback(drawing_area, XmNinputCallback, drawing_area_input, NULL);

	XtRealizeWidget(toplevel);
	XtMainLoop();
}
@EOF

chmod 644 drawing_area.c

exit 0