[comp.windows.x] Two Athena widget questions.

leei@McRCIM.McGill.EDU (Lee Iverson) (03/29/91)

Alright, these are getting to be too much...

1) Is there any way to get a viewport widget to recognize a child
downsize?  No matter what I try (short of rewriting the Viewport
widget), any requests that result in reducing the size of the child
widget leave the effective viewport exactly the same size.  This has
got to be a bug, but I can't be sure since there is precious little
information about *promised* behaviour in the documentation.

The only restriction on shrinking specified is that the frame will not
shrink with the child unless it's parent allows it.  What I'm
referring to is the shrinking of an oversized child to a smaller (but
still oversize size).  The limits of the scrollbars will still reflect
the original (largest size).

2) Is the promise that an asciiTextWidget will call a callback when
the data is modified a lie?  I can't seem to register the callback.
The promise that I'm referring to is in Section 5.5.1 of the Athena
Widget Set docs.  Under a description of the AsciiText resources, the
entry for callback is:

callbacks  The callbacks registered on this resource will be called
	   every time the text buffer changes.  This is an AsciiSrc
	   resource.

But with 'dir' an asciiTextWidget, the following call gives the
runtime error:
	XtAddCallback(dir, XtNcallback, fdUpdateFileList, dlog );

Warning: Cannot find callback list in XtAddCallbacks

What's up?  Shouldn't this be inherited behaviour?

If anyone is serious about answering these, I enclose a simple example
(an initial attempt to create a file dialog box similar to that
available on a Mac).  There are minor problems with the list widget
here that I am in the process of working out, and definite resizing
problems with the data entry widgets.  I think I can figure these out
(although I'd appreciate any help offered).  The keys are:

1) behaviour when (e.g. data is modified in the dirName widget).  This
should cause the fileList widget to be updated, but doesn't.

2) size changes as directory entries are clicked in the fileList
window.  The width of the window changes (seemingly randomly) and the
length never decreases from the maximum specified!  The first appears
to be a List widget problem (or more likely in my understanding of
it, although it does seem as if forceColumns and defaultColumns have
no effect), but the second is definitely the Viewport bug!?

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Thu Mar 28 11:12:27 1991
# Run this through sh to create:
#	Imakefile
#	test_file.c
#	FileDialog.c
#	FileDialog.h
#	XFileDialog.ad.h
#	XFileDialog.ad
echo x - Imakefile \(387 characters\)
sed 's/^X//' > Imakefile << \EOF
XSYS_LIBRARIES=	-lXaw -lXt -lXext -lXmu -lX11
X
XHDRS=   FileDialog.h XFileDialog.ad.h
XSRCS=	test_file.c FileDialog.c
XOBJS=	test_file.o FileDialog.o
X
XPROGRAMS= test_file
X
XComplexProgramTarget(test_file)
X
XXFileDialog.ad.h: XFileDialog.ad
X	ad2c XFileDialog.ad > XFileDialog.ad.h
X
Xtest_file.c:: XFileDialog.ad.h
X
Xfdialog.shar: Imakefile $(SRCS) $(HDRS) XFileDialog.ad
X	shar $^ > fdialog.shar
X
EOF
if test 387 -ne "`wc -c Imakefile`"
then
echo shar: error transmitting Imakefile \(should have been 387 characters\)
fi
echo x - test_file.c \(1848 characters\)
sed 's/^X//' > test_file.c << \EOF
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X
X#include <X11/Shell.h>
X
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Box.h>
X
X#include "FileDialog.h"
X
X/*
X *	Widget and non-widget resources if the application defaults
X *	file can't be found.
X *	[ Generated automatically from XFileDialog.ad. ]
X */
Xstatic String fallbackResources[] = {
X#include "XFileDialog.ad.h"
X	NULL
X};
X
Xstatic void
XQuit( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    exit(0);
X}
X
Xstatic void
XGetFileDialog( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    FileDialog dlog = (FileDialog) client_data;
X    char *fname = useFileDialog(dlog);
X
X    printf( "File dialog returned: %s\n", fname );
X}
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    XtAppContext app_context;
X    Widget topLevel;
X    FileDialog fdialog;
X
X    topLevel = XtVaAppInitialize( &app_context, "XFileDialog",
X				  NULL, 0,
X				  &argc, argv,
X				  fallbackResources,
X				  NULL );
X    
X    XtAddConverter("String", "Bitmap",
X		   XmuCvtStringToBitmap, screenConvertArg, 1 );
X    XtAddConverter("String", "Pixmap", 
X		   XmuCvtStringToBitmap, screenConvertArg, 1 );
X
X    fdialog = makeFileDialog( "file", topLevel );
X    
X    {
X	Widget box = XtVaCreateManagedWidget("box", boxWidgetClass,
X					     topLevel, NULL);
X
X	Widget quit = XtVaCreateManagedWidget(
X		"quit",	/* widget name */
X		commandWidgetClass,	/* widget class */
X		box,	/* parent widget*/
X		NULL);              /* terminate varargs list */
X
X	Widget pressme = XtVaCreateManagedWidget(
X		"pressme",	/* widget name	 */
X		commandWidgetClass,	/* widget class */
X		box,	/* parent widget*/
X		NULL);              /* terminate varargs list */
X
X	XtAddCallback( quit, XtNcallback, Quit, 0);
X	XtAddCallback( pressme, XtNcallback, GetFileDialog, fdialog);
X    }
X
X    XtRealizeWidget(topLevel);
X    XtAppMainLoop(app_context);
X}
EOF
if test 1848 -ne "`wc -c test_file.c`"
then
echo shar: error transmitting test_file.c \(should have been 1848 characters\)
fi
echo x - FileDialog.c \(6416 characters\)
sed 's/^X//' > FileDialog.c << \EOF
X#include <stdlib.h>
X#include <string.h>
X
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Shell.h>
X
X#include <X11/Xaw/Dialog.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/AsciiText.h>
X#include <X11/Xaw/List.h>
X#include <X11/Xaw/Scrollbar.h>
X#include <X11/Xaw/Viewport.h>
X
X#include "FileDialog.h"
X
Xstatic void
XfdSelected( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    FileDialog dlog = (FileDialog) client_data;
X    
X    XtPopdown(dlog->popup);
X    dlog->done = 1;
X    dlog->selected = 1;
X}
X
Xstatic void
XfdCancelled( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    FileDialog dlog = (FileDialog) client_data;
X    
X    XtPopdown(dlog->popup);
X    dlog->done = 1;
X    dlog->selected = 0;
X}
X
XfdUpdateFileList( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    FileDialog dlog = (FileDialog) client_data;
X    struct direct **dlist, **dp;
X    char *dname;
X    String *list;
X    int i, num, maxwidth;
X    extern int alphasort();
X
X    /* Clean up previous list... */
X    XtVaGetValues(dlog->file_list, XtNlist,&list, XtNnumberStrings,&num, NULL);
X    if ( list && strcmp(list[0],"fileList") ) {
X	for ( i = 0; i < num; ++i ) free(list[i]);
X	free(list);
X    }
X
X    /* Get directory list. */
X    XtVaGetValues( dlog->dir, XtNstring, &dname, NULL );
X    if ( (num=scandir( dname, &dlist, NULL, alphasort )) < 0 )
X      return;
X
X    /* Format it for use in the fileList widget */
X    list = (String *) malloc((num+1) * sizeof(String));
X    for ( i = 0, dp = dlist; i < num; ++i, ++dp ) {
X	list[i] = strdup((*dp)->d_name);
X    }
X    list[num] = 0;
X
X    /* Inform fileList widget of the change. */
X    XawListChange(dlog->file_list, list, num, 0, False);
X    XtVaSetValues(dlog->file_list, 
X		  XtNforceColumns, True, XtNdefaultColumns, 1, 
X		  NULL);
X
X    free(dlist);
X}
X
XfdSelectFile( Widget w, XtPointer client_data, XtPointer call_data )
X{
X    FileDialog dlog = (FileDialog) client_data;
X    XawListReturnStruct *list_elem = (XawListReturnStruct*) call_data;
X    char fname[MAXPATHLEN];
X    char *dname;
X    struct stat sbuf;
X
X    XtVaGetValues( dlog->dir, XtNstring, &dname, NULL );
X    strcpy( fname, dname );
X    strcat( fname, "/" );
X    strcat( fname, list_elem->string );
X    if ( stat(fname,&sbuf) < 0 ) return;
X
X    if ( S_ISDIR(sbuf.st_mode) ) {
X	chdir(fname);
X	XtVaSetValues( dlog->dir, XtNstring, getwd(fname), NULL );
X	fdUpdateFileList( w, client_data, 0 );
X    } else {
X	XtVaSetValues( dlog->file_name, XtNstring, list_elem->string, NULL );
X    }
X}
X
XFileDialog
XmakeFileDialog( char *name, Widget parent )
X{
X    FileDialog dlog;
X    Widget pshell, dialog;
X    char dname[MAXPATHLEN];
X    
X    if ( !name ) name = "fileDialog";
X
X    getwd(dname);
X
X    pshell = XtVaCreatePopupShell(name,transientShellWidgetClass,parent,NULL);
X    dialog = XtVaCreateManagedWidget("dialog", formWidgetClass, pshell, NULL);
X    
X    dlog = (FileDialog) malloc(sizeof(*dlog));
X    dlog->popup = pshell;
X    dlog->dialog = dialog;
X    dlog->restriction = NULL;
X    dlog->selected = 0;
X
X    {
X	Widget dlabel =
X	  XtVaCreateManagedWidget("dirLabel", labelWidgetClass, dialog,
X				  XtNresizable, False,
X				  XtNleft, XtChainLeft,
X				  XtNright, XtChainLeft,
X				  NULL );
X	Widget dir =
X	  XtVaCreateManagedWidget("directory", asciiTextWidgetClass, dialog,
X				  XtNstring, dname,
X				  XtNresizable, True,
X				  XtNresize, XawtextResizeWidth,
X				  XtNeditType, XawtextEdit,
X				  XtNfromHoriz, dlabel,
X				  XtNleft, XtChainLeft,
X				  XtNright, XtChainRight,
X				  XtNhorizDistance, 0,
X				  NULL );
X
X	Widget file_vp =
X	  XtVaCreateManagedWidget("fileViewport", viewportWidgetClass, dialog,
X				  XtNheight, 80,
X				  XtNresizable, True,
X				  XtNallowHoriz, False,
X				  XtNallowVert, True,
X				  XtNresizable, True,
X				  XtNfromVert, dir,
X				  XtNleft, XtChainLeft,
X				  XtNright, XtChainRight,
X				  XtNtop, XtChainTop,
X				  XtNbottom, XtChainBottom,
X				  NULL );
X	Widget file_list =
X	  XtVaCreateManagedWidget("fileList", listWidgetClass, file_vp, NULL);
X
X	Widget flabel =
X	  XtVaCreateManagedWidget("fileLabel", labelWidgetClass, dialog,
X				  XtNresizable, False,
X				  XtNleft, XtChainLeft,
X				  XtNright, XtChainLeft,
X				  XtNfromVert, file_vp,
X				  NULL );
X	Widget file_name =
X	  XtVaCreateManagedWidget("fileName", asciiTextWidgetClass, dialog,
X				  XtNresizable, True,
X				  XtNresize, XawtextResizeWidth,
X				  XtNeditType, XawtextEdit,
X				  XtNfromVert, file_vp,
X				  XtNfromHoriz, flabel,
X				  XtNleft, XtChainLeft,
X				  XtNright, XtChainRight,
X				  XtNhorizDistance, 0,
X				  NULL );
X
X	dlog->dir = dir;
X	dlog->file_name = file_name;
X	dlog->file_list = file_list;
X	fdUpdateFileList(file_list,dlog,0);
X	XtAddCallback(file_list, XtNcallback, fdSelectFile, dlog );
X	XtAddCallback(dir, XtNcallback, fdUpdateFileList, dlog );
X    }
X
X    {
X	Widget select = 
X	  XtVaCreateManagedWidget("selectButton", commandWidgetClass, dialog, 
X				  XtNresizable, False,
X				  XtNfromVert, dlog->file_name,
X				  NULL );
X	Widget cancel = 
X	  XtVaCreateManagedWidget("cancelButton", commandWidgetClass,dialog, 
X				  XtNresizable, False,
X				  XtNfromVert, dlog->file_name,
X				  XtNfromHoriz, select,
X				  NULL );
X    
X	XtAddCallback( select, XtNcallback, fdSelected, dlog );
X	XtAddCallback( cancel, XtNcallback, fdCancelled, dlog );
X    }
X
X    return dlog;
X}
X
Xchar *
XuseFileDialog( FileDialog dlog )
X{
X    Widget popup = dlog->popup;
X    Widget parent = XtParent(popup);
X    Position x, y;
X    Dimension width, height;
X    Dimension p_width, p_height;
X
X    XtVaGetValues(parent, XtNwidth, &width, XtNheight, &height, NULL);
X    XtVaGetValues(popup, XtNwidth, &p_width, XtNheight, &p_height, NULL);
X    XtTranslateCoords(parent, (width-p_width)/2, (height-p_height)/2, &x, &y);
X    XtVaSetValues(popup, XtNx, x, XtNy, y, NULL);
X
X    dlog->done = 0;
X    XtPopup( popup, XtGrabExclusive );
X
X    while ( !dlog->done ) {
X	XEvent event;
X        XNextEvent(XtDisplay(popup),&event);
X        XtDispatchEvent(&event);
X    }
X
X    if ( dlog->selected ) {
X	char fullname[MAXPATHLEN];
X	char *dname, *fname;
X	XtVaGetValues( dlog->dir, XtNstring, &dname, NULL );
X	XtVaGetValues( dlog->file_name, XtNstring, &fname, NULL );
X	strcpy( fullname, dname );
X	strcat( fullname, "/" );
X	strcat( fullname, fname );
X	return fullname;
X    } else {
X	return 0;
X    }
X}
EOF
if test 6416 -ne "`wc -c FileDialog.c`"
then
echo shar: error transmitting FileDialog.c \(should have been 6416 characters\)
fi
echo x - FileDialog.h \(372 characters\)
sed 's/^X//' > FileDialog.h << \EOF
X#ifndef _FileDialog_h_
X#define _FileDialog_h_
X
Xtypedef struct {
X    Widget popup;
X    Widget dialog;
X    Widget dir;
X    Widget file_list;
X    Widget file_name;
X    int (*restriction)(char *);
X    int done;
X    int selected;
X} *FileDialog;
X
XFileDialog
X  makeFileDialog( char *name, Widget parent );
Xchar *
X  useFileDialog( FileDialog dlog );
X
X#endif /* _FileDialog_h_ */
X
EOF
if test 372 -ne "`wc -c FileDialog.h`"
then
echo shar: error transmitting FileDialog.h \(should have been 372 characters\)
fi
echo x - XFileDialog.ad.h \(354 characters\)
sed 's/^X//' > XFileDialog.ad.h << \EOF
X"*quit.label: Quit",
X"*pressme.label: Press Me",
X"*file*ShapeStyle: Oval",
X"*file*dialog.backgroundPixmap: light_gray",
X"*file*BorderWidth: 0",
X"*file*Command.BorderWidth: 2",
X"*file*Viewport.BorderWidth: 1",
X"*file*dirLabel.label: Directory:",
X"*file*fileLabel.label: File Name:",
X"*file*selectButton.label: Select",
X"*file*cancelButton.label: Cancel",
EOF
if test 354 -ne "`wc -c XFileDialog.ad.h`"
then
echo shar: error transmitting XFileDialog.ad.h \(should have been 354 characters\)
fi
echo x - XFileDialog.ad \(324 characters\)
sed 's/^X//' > XFileDialog.ad << \EOF
X*quit.label: Quit
X*pressme.label: Press Me
X
X*file*ShapeStyle: Oval
X*file*dialog.backgroundPixmap: light_gray
X*file*BorderWidth: 0
X*file*Command.BorderWidth: 2
X*file*Viewport.BorderWidth: 1
X
X*file*dirLabel.label: Directory:
X*file*fileLabel.label: File Name:
X
X*file*selectButton.label: Select
X*file*cancelButton.label: Cancel
EOF
if test 324 -ne "`wc -c XFileDialog.ad`"
then
echo shar: error transmitting XFileDialog.ad \(should have been 324 characters\)
fi
exit 0
# end of shell archive
-- 

Lee Iverson			McGill Research Centre for Intelligent Machines
leei@mcrcim.mcgill.edu		Computer Vision and Robotics Lab
				McGill University, Montreal

converse@expo.lcs.mit.EDU (03/29/91)

	2) Is the promise that an asciiTextWidget will call a callback when
	the data is modified a lie?  I can't seem to register the callback.
	The promise that I'm referring to is in Section 5.5.1 of the Athena
	Widget Set docs.  Under a description of the AsciiText resources, the
	entry for callback is:

	callbacks  The callbacks registered on this resource will be called
		   every time the text buffer changes.  This is an AsciiSrc
		   resource.


The Ascii Text widget does not have a callback resource.
Add the callback to the Ascii Source, not the Ascii Text.
You can do GetValues on the AsciiText's textSource resource to get the
source object, and add the callback to the source object.


	1) Is there any way to get a viewport widget to recognize a child
	downsize?  No matter what I try (short of rewriting the Viewport
	widget), any requests that result in reducing the size of the child
	widget leave the effective viewport exactly the same size.


This may due to the Viewport's handling of its child's request for a 
size change, or it may be due to the Viewport's parent's handling of
the Viewport's request for a size change, or it's parent's parent,
and so on, on up to the Shell.  I don't have any more time now.


Donna Converse

leei@thunder.mcrcim.mcgill.EDU (04/10/91)

In message <9103281952.AA15167@excess.lcs.mit.edu> you write:
>
>
>
>	2) Is the promise that an asciiTextWidget will call a callback when
>	the data is modified a lie?  I can't seem to register the callback.
>	The promise that I'm referring to is in Section 5.5.1 of the Athena
>	Widget Set docs.  Under a description of the AsciiText resources, the
>	entry for callback is:
>
>	callbacks  The callbacks registered on this resource will be called
>		   every time the text buffer changes.  This is an AsciiSrc
>		   resource.
>
>
>The Ascii Text widget does not have a callback resource.
>Add the callback to the Ascii Source, not the Ascii Text.
>You can do GetValues on the AsciiText's textSource resource to get the
>source object, and add the callback to the source object.
>

Thanks for the help.  This seems to work fine, but as I use it I become unclear
on the intended semantics of the callback.  At what time is the callback
generated?  From a quick scan through the AsciiSrc source code, it seems to be
sent before the replace operation has actually been completed, so if I do a
XtVaGetValues( w, XtNstring, &name, NULL) in my callback routine, I will get
the unchanged value!  Well, that is supposing that it works.  In fact, if the
useStringInPlace property is False, this call causes a core dump since the
initialization performed before the XtCallCalbacks call in ReplaceText() is
invalidated by the XawAsciiSave() call via GetValuesHook().  I'd call it a bug,
but since the semantics of the callback seem undefined (at least anywhere I can
see in section 5 of the Athena Widget Set docs) it is not clear to me what I'm
allowed to do in this callback and what not.  If you decide this is a bug, let
me know and I'll file a real bug report.  If the semantics are intended to be
such that by the time the callback is invoked, the string resource should
actually be changed, then let me know that too.

------------------------------------------------------------------------------
Lee Iverson			McGill Research Centre for Intelligent Machines
leei@mcrcim.mcgill.edu		Computer Vision and Robotics Lab
				McGill University, Montreal