rick@pcrat.uucp (Rick Richardson) (07/17/90)
I'm trying to make a Form that contains some buttons at the top, and a scrollable list of things at the bottom. If the User resizes the form, I want the scrollable list to change size so that it fills the form completely, except for the area occupied by the buttons at the top. E.G. I want the form to look like this no matter how big or small the window is: +-------------------------+ | Button | +-------------------------+ | Item N ^ | | Item N+1 | | | Item N+2 | | | Item N+3 v | | <--------------------> | +-------------------------+ I've tried a couple things. If I use a SelectionBox, the list portion stretches automatically in the horizontal direction, but not vertically. Plus, I just want the list portion, anyhow. If I used the SelectionBox, I'd want to tell it (somehow) to make visibleItems variable, and forget the Text area and Buttons. Using a ScrolledList, I can't get either dimension to stretch with the form. I fooled around alot with the policies. PLUS, the widget positions itself *under* the button, as if the button had 0 height, even though the attachment constraints are the same as for the SelectionBox I tried. That might be a bug. Perhaps these widgets just aren't appropriate. Perhaps I need to use some callbacks. Any suggestions will be gratefully received. I'm enclosing the (bare minimum) .uil file so you can better see what I've tried. All this is using Motif 1.0. -Rick Richardson module prototype version = 'v1.0' names = case_sensitive include file 'XmAppl.uil'; object ft_main : XmForm { controls { XmPushButton button1; ! ! Comment out one or the other ! XmSelectionBox try_sel; ! XmScrolledList try_list; }; arguments { XmNwidth = 300; XmNheight = 300; }; }; object button1 : XmPushButton { arguments { XmNtopAttachment = XmATTACH_FORM; XmNleftAttachment = XmATTACH_FORM; XmNrightAttachment = XmATTACH_FORM; }; }; object try_selbox : XmSelectionBox { arguments { XmNtopAttachment = XmATTACH_WIDGET; XmNtopWidget = XmPushButton button1; XmNleftAttachment = XmATTACH_FORM; XmNrightAttachment = XmATTACH_FORM; XmNbottomAttachment = XmATTACH_FORM; XmNlistVisibleItemCount = 5; }; }; object try_list : XmScrolledList { arguments { XmNtopAttachment = XmATTACH_WIDGET; XmNtopWidget = XmPushButton button1; XmNleftAttachment = XmATTACH_FORM; XmNrightAttachment = XmATTACH_FORM; XmNbottomAttachment = XmATTACH_FORM; XmNvisibleItemCount = 5; XmNscrollBarDisplayPolicy = XmSTATIC; XmNlistSizePolicy = XmCONSTANT; XmNvisualPolicy = XmCONSTANT; }; }; end module; -- Rick Richardson - PC Research, Inc., uunet!pcrat!rick, (201) 389-8963
rick@pcrat.uucp (Rick Richardson) (07/17/90)
In article <1990Jul16.172955.11321@pcrat.uucp> rick@pcrat.uucp (Rick Richardson) writes: >I'm trying to make a Form that contains some buttons at the >top, and a scrollable list of things at the bottom. I think I've answered my own question. I gave up on using the widget with the enticing name ScrolledList. Instead, I used the raw ScrolledWindow, at first with a List inside it, then with a Form inside it. The Form contains a Label and a List, which is better for what I wanted to do, anyway. I did run into what I'd consider another bug, which you can read about in the UIL comments. Thanks to all those people who I'm sure were ready to point me in the right direction. If you still want to, feel free to comment on my use of UIL (modulo bracing and indenting). -Rick P.S. Filling in the list creation C code, and the pushbutton callback is an exercise for the reader. If you haven't used UIL before, snag the fairly generic hellomotif.c scaffold from /usr/lib/X11/examples. I think the theory is that a Human Factors person is supposed to be able to write UIL and run it against the scaffold. When the whole interface is fleshed out, it becomes the input to a programmer who writes the C code to make it really do that, using most of the UIL as supplied from Human Factors. Of course, the UIL manual isn't written to be readable by those folks, and is barely readable by a programmer, so the theory may be shot full of holes. Specific complaint: dump the BNF into an appendix, and replace with examples. OSF: Feel free to use this one. ! ! Sample UIL specification of a stretchable list, with header ! module fr version = 'v1.0' names = case_sensitive include file 'XmAppl.uil'; object ft_main : XmForm { controls { XmPushButton kill_button; XmScrolledWindow scroll_window; }; arguments { XmNheight = 200; XmNwidth = 300; }; }; object kill_button : XmPushButton { arguments { XmNtopAttachment = XmATTACH_FORM; XmNleftAttachment = XmATTACH_FORM; XmNrightAttachment = XmATTACH_FORM; XmNlabelString = "Select a Process to Kill, Then Push Me"; }; }; object scroll_window : XmScrolledWindow { controls { XmForm scroll_form; }; arguments { XmNtopAttachment = XmATTACH_WIDGET; XmNtopWidget = XmPushButton kill_button; XmNleftAttachment = XmATTACH_FORM; XmNrightAttachment = XmATTACH_FORM; XmNbottomAttachment = XmATTACH_FORM; XmNscrollingPolicy = XmAUTOMATIC; XmNvisualPolicy = XmCONSTANT; XmNworkWindow = XmForm scroll_form; }; }; object scroll_form : XmForm { controls { XmLabel scroll_header; XmList scroll_list; }; }; ! ! Although it is tempting to put ???Attachment constraints ! on scroll_header and scroll_list, don't do it. It triggers ! some kind of bug in Motif, and the scroll_list gets trashed. ! It seems to do 'the right thing' without them (luckily). ! object scroll_header : XmLabel { arguments { XmNlabelString = " UID PID PPID C STIME TTY TIME COMMAND "; ! XmNtopAttachment = XmATTACH_FORM; ! XmNleftAttachment = XmATTACH_FORM; }; }; value scroll_list_items : exported string_table ( " root 0 0 0 Jul 10 ? 0:03 sched", " root 1 0 0 Jul 10 ? 3:50 /etc/init ", " root 2 0 0 Jul 10 ? 4:08 vhand", " root 3 0 0 Jul 10 ? 3:21 bdflush", " root 97 1 0 Jul 10 console 0:01 /etc/getty console console ", " rick 101 1 0 Jul 10 vt01 0:19 -ksh ", " root 9124 1 0 16:43:46 ttyp0 0:01 /etc/faxsrv ", " root 9125 9124 0 16:43:46 ttyp0 0:01 faxrun1 -Tjfax -D/dev/jfax0", " root 9126 9124 0 16:43:46 ttyp0 0:01 faxrun2 -Tbfax -D/dev/bfax0", " root 9127 9124 0 16:43:47 ttyp0 0:01 faxrun3 -Tbfax -D/dev/bfax1", " root 9128 9124 0 16:43:47 ttyp0 0:03 faxrun4 -Tefax -D/dev/tty00", " root 9129 9124 0 16:43:48 ttyp0 0:03 faxrun5 -Tefax -D/dev/tty01", " root 75 1 0 Jul 10 ? 0:21 /etc/cron ", " root 79 1 0 Jul 10 ? 0:38 /usr/lib/lpsched ", " root 6242 1 0 Jul 14 vt02 0:00 /etc/getty /dev/vt02 vt02 ", " root 6243 1 0 Jul 14 vt03 0:00 /etc/getty /dev/vt03 vt03 ", " root 6244 1 0 Jul 14 vt04 0:00 /etc/getty /dev/vt04 vt04 ", " rick 8300 101 0 23:42:07 vt01 0:00 xinit ", " rick 8301 8300 9 23:42:07 vt05 7:05 X :0 ", " rick 8302 8300 3 23:42:13 ? 1:27 xterm -geometry 80x24+0+0", " rick 8303 8302 0 23:42:14 ? 0:23 /usr3/bin/X11/uwm ", " rick 8304 8302 1 23:42:19 ttyp0 0:09 ksh " ); object scroll_list : XmList { arguments { ! XmNtopAttachment = XmATTACH_WIDGET; ! XmNtopWidget = XmLabel scroll_header; ! XmNleftAttachment = XmATTACH_FORM; ! XmNrightAttachment = XmATTACH_FORM; ! XmNbottomAttachment = XmATTACH_FORM; XmNitems = scroll_list_items; XmNitemCount = 22; XmNvisibleItemCount = 22; }; }; end module; -- Rick Richardson | Looking for FAX software for UNIX/386 ??? Ask About: |Mention PC Research,Inc.| FaxiX - UNIX Facsimile System (tm) |FAX# for uunet!pcrat!rick| FaxJet - HP LJ PCL to FAX (Send WP,Word,Pagemaker...)|Sample (201) 389-8963 | JetRoff - troff postprocessor for HP LaserJet and FAX|Output
rick@pcrat.uucp (Rick Richardson) (07/17/90)
In article <1990Jul16.223021.11654@pcrat.uucp> rick@pcrat.UUCP (Rick Richardson) writes: >I think I've answered my own question. Actually, what I thought was fixed is really still broken. It seems the /etc/sched List entry was hiding behind the header Label. So, it looks like I'm damned if I do, and damned if I don't. That is, with the attachments specified for the children of the scroll Form I get complete trash displayed for the List. If the attachments are left off, then the header Label child and the List child are overlaid on the form. I got one piece of advice that said that a workaround is to add the bottom and right attachments after the Form widget has been realized. That, of course, must be done from C. Making the utility of UIL less worthwhile. I think the solution is to toss the Form widget and get something else (Table was mentioned). Form seems to be terribly broken. On the bright side, if I keep tossing widgets, I'll eventually get back to just Xlib, and my apps will be relatively small. :-) -Rick P.S. If you aren't following this, see the 2nd referenced posting. -- Rick Richardson - PC Research, Inc., uunet!pcrat!rick, (201) 389-8963
rick@pcrat.UUCP (Rick Richardson) (07/21/90)
In article <1990Jul17.014256.11899@pcrat.uucp> rick@pcrat.UUCP (Rick Richardson) writes: >Actually, what I thought was fixed is really still broken. >I think the solution is to toss the Form widget and get something >else (Table was mentioned). Form seems to be terribly broken. I got the Table widget from the Widget Creation Library, and nazgul@alphalpha.com (Kee Hinckley) sent me the patches to make it Motif-ized. I then recoded my example in C, and included a command line option to use the Table widget instead of the Form widget as the inner widget container. It all works as expected using the Table widget. I've appended the C version in a SHAR file for those who care to try this themselves. Also, the comments indicate the various effects I discovered when trying to use the Form. If the OSF is listening, I now consider the Form to be a broken widget that needs fixing. Also, I couldn't find VARARGS versions of XtCreateManagedWidget() and XtSetValues() in my X11R3 libXt.a, so I've included my own versions of vXtCreateManagedWidget() and vXtSetValues() as well. The method used in all the books is so utterly ugly I couldn't stand it. -Rick Richardson #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ftm.c # This archive created: Sat Jul 21 11:52:09 1990 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'ftm.c' then echo shar: "will not over-write existing file 'ftm.c'" else sed 's/^X//' << \SHAR_EOF > 'ftm.c' X/* X * ftm.c X * Test Program for Stretchable List (C version, taken from UIL version) X * X * $ ftm 0 # the children of ScrollForm are not constrained X * $ ftm 1 # the children of ScrollForm are constrained X * $ ftm 2 # Use the PD Table widget instead of a Form for ScrollForm X * X * In the first invocation, everything comes up looking normal, except that X * the first line of the ScrollList is buried under the ScrollHdr. X * X * In the second invocation, the vertical ScrollBar of the List is missing, X * and only about 50% of the first line of the ScrollList is displayed. E.G. X * the letters are clipped. X * X * In the third invocation, everything works. Obviously, Table has much X * better (i.e. working) geometry management for its children. X * X * I would expect the second case to be the proper way to code this, but X * it sure doesn't work right on this system, ISC Motif 1.0, X11R3. X * X * If you don't have the PD Table widget, #define NO_TABLE_WIDGET. X * In that case, ftm 2 (the invocation that works) won't be available. X * X * Rick Richardson, uunet!pcrat!rick, rick@pcrat.pcr.com X */ X#include <stdio.h> X#include <varargs.h> X#include <X11/StringDefs.h> X#include <X11/Intrinsic.h> X#include <Xm/Xm.h> X#include <Xm/Form.h> X#include <Xm/PushB.h> X#include <Xm/Label.h> X#include <Xm/ScrolledW.h> X#include <Xm/List.h> X X#ifndef NO_TABLE_WIDGET X#include "Table.h" X#endif X X/* X * Convenience functions X */ Xextern Widget vXtCreateManagedWidget(); Xextern void vXtSetValues(); X#define ASIZEOF(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) X#define AV (XtArgVal) X#define XMSC(S) XmStringCreate(S, XmSTRING_DEFAULT_CHARSET) X X/* X * Widget Heirarchy X */ XWidget Top; /* Shell */ XWidget OuterForm; /* Form */ XWidget KillButton; /* PushButton */ XWidget ScrollWindow; /* ScrolledWindow */ XWidget ScrollForm; /* Form or Table */ XWidget ScrollHdr; /* Label */ XWidget ScrollList; /* List */ X X/* X * Strings to use for labels and list X */ X#define KILL_LABEL "Select a Process to Kill and Push Me" X#define SCROLL_HDR \ X " UID PID PPID C STIME TTY TIME COMMAND " X Xstatic char *ListItems[] = X{ X" root 0 0 0 Jul 10 ? 0:03 sched", X" root 1 0 0 Jul 10 ? 3:50 /etc/init ", X" root 2 0 0 Jul 10 ? 4:08 vhand", X" root 3 0 0 Jul 10 ? 3:21 bdflush", X" root 97 1 0 Jul 10 console 0:01 /etc/getty console console ", X" rick 101 1 0 Jul 10 vt01 0:19 -ksh ", X" root 9124 1 0 16:43:46 ttyp0 0:01 /etc/faxsrv ", X" root 9125 9124 0 16:43:46 ttyp0 0:01 faxrun1 -Tjfax -D/dev/jfax0", X" root 9126 9124 0 16:43:46 ttyp0 0:01 faxrun2 -Tbfax -D/dev/bfax0", X" root 9127 9124 0 16:43:47 ttyp0 0:01 faxrun3 -Tbfax -D/dev/bfax1", X" root 9128 9124 0 16:43:47 ttyp0 0:03 faxrun4 -Tefax -D/dev/tty00", X" root 9129 9124 0 16:43:48 ttyp0 0:03 faxrun5 -Tefax -D/dev/tty01", X" root 75 1 0 Jul 10 ? 0:21 /etc/cron ", X" root 79 1 0 Jul 10 ? 0:38 /usr/lib/lpsched ", X" root 6242 1 0 Jul 14 vt02 0:00 /etc/getty /dev/vt02 vt02 ", X" root 6243 1 0 Jul 14 vt03 0:00 /etc/getty /dev/vt03 vt03 ", X" root 6244 1 0 Jul 14 vt04 0:00 /etc/getty /dev/vt04 vt04 ", X" rick 8300 101 0 23:42:07 vt01 0:00 xinit ", X" rick 8301 8300 9 23:42:07 vt05 7:05 X :0 ", X" rick 8302 8300 3 23:42:13 ? 1:27 xterm -geometry 80x24+0+0", X" rick 8303 8302 0 23:42:14 ? 0:23 /usr3/bin/X11/uwm ", X" rick 8304 8302 1 23:42:19 ttyp0 0:09 ksh " X}; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X XmString *litems; X register int i; X int mode = 0; X X /* X * Convert Strings to Motif format X */ X litems = (XmString *) XtMalloc(ASIZEOF(ListItems) * sizeof(XmString)); X for (i = 0; i < ASIZEOF(ListItems); ++i) X litems[i] = XMSC(ListItems[i]); X X /* X * Create the Widget Heirarchy X */ X Top = XtInitialize(argv[0], argv[0], NULL, 0, &argc, argv); X X if (argc > 1) mode = atoi(argv[1]); X else {fprintf(stderr, "Usage: ftm [0|1|2]\n"); exit(1);} X X OuterForm = vXtCreateManagedWidget("OuterForm", X xmFormWidgetClass, Top, X XtNwidth, AV 300, X XtNheight, AV 200, X (String) NULL); X X KillButton = vXtCreateManagedWidget("KillButton", X xmPushButtonWidgetClass, OuterForm, X XmNtopAttachment, AV XmATTACH_FORM, X XmNleftAttachment, AV XmATTACH_FORM, X XmNrightAttachment, AV XmATTACH_FORM, X XmNlabelString, AV XMSC(KILL_LABEL), X (String) NULL); X X ScrollWindow = vXtCreateManagedWidget("ScrollWindow", X xmScrolledWindowWidgetClass, OuterForm, X XmNtopAttachment, AV XmATTACH_WIDGET, X XmNtopWidget, AV KillButton, X XmNleftAttachment, AV XmATTACH_FORM, X XmNrightAttachment, AV XmATTACH_FORM, X XmNbottomAttachment, AV XmATTACH_FORM, X XmNscrollingPolicy, AV XmAUTOMATIC, X XmNvisualPolicy, AV XmCONSTANT, X /* XmNworkWindow, AV scroll_form,*/ X (String) NULL); X X#ifndef NO_TABLE_WIDGET Xif (mode==2) X ScrollForm = vXtCreateManagedWidget("table", X tableWidgetClass, ScrollWindow, X (String) NULL); Xelse X#endif X ScrollForm = vXtCreateManagedWidget("ScrollForm", X xmFormWidgetClass, ScrollWindow, X (String) NULL); X X ScrollHdr = vXtCreateManagedWidget("ScrollHdr", X xmLabelWidgetClass, ScrollForm, X XmNlabelString, AV XMSC(SCROLL_HDR), X mode == 1 ? X XmNtopAttachment : (String) NULL, X AV XmATTACH_FORM, X XmNleftAttachment, AV XmATTACH_FORM, X (String) NULL); X X ScrollList = vXtCreateManagedWidget("ScrollList", X xmListWidgetClass, ScrollForm, X XmNitems, AV litems, X XmNitemCount, AV ASIZEOF(ListItems), X XmNvisibleItemCount, AV ASIZEOF(ListItems), X mode == 1 ? X XmNtopAttachment : (String) NULL, X AV XmATTACH_WIDGET, X XmNtopWidget, AV ScrollHdr, X XmNleftAttachment, AV XmATTACH_FORM, X XmNrightAttachment, AV XmATTACH_FORM, X XmNbottomAttachment, AV XmATTACH_FORM, X (String) NULL); X X /* X * Now fix up stuff we couldn't specify before X */ X vXtSetValues(ScrollWindow, XmNworkWindow, AV ScrollForm, (String) NULL); X# ifndef NO_TABLE_WIDGET X if (mode == 2) X { X XtTblConfig(ScrollHdr, X /* pos */ 0, 0, X /* span*/ 1, 1, X TBL_SM_HEIGHT); X XtTblConfig(ScrollList, X /* pos */ 0, 1, X /* span*/ 1, 1, X TBL_DEF_OPT); X } X# endif X X XtRealizeWidget(Top); X XtMainLoop(); X} X X/* X * Variable arg list version of XtCreateManagedWidget X */ X/* VARARGS */ XWidget XvXtCreateManagedWidget(va_alist) Xva_dcl X{ X va_list args; X X String name; X String class; X Widget parent; X X# define NXARGS 100 X Arg xargs[NXARGS]; X register int i; X X va_start(args); X name = va_arg(args, String); X class = va_arg(args, String); X parent = va_arg(args, Widget); X X for (i = 0; i < NXARGS; ++i) X { X xargs[i].name = va_arg(args, String); X if (xargs[i].name == NULL) break; X xargs[i].value = va_arg(args, XtArgVal); X } X va_end(args); X return (XtCreateManagedWidget(name, class, parent, xargs, i)); X# undef NXARGS X} X X/* VARARGS */ Xvoid XvXtSetValues(va_alist) Xva_dcl X{ X va_list args; X X Widget w; X X# define NXARGS 100 X Arg xargs[NXARGS]; X register int i; X X va_start(args); X w = va_arg(args, Widget); X X for (i = 0; i < NXARGS; ++i) X { X xargs[i].name = va_arg(args, String); X if (xargs[i].name == NULL) break; X xargs[i].value = va_arg(args, XtArgVal); X } X va_end(args); X XtSetValues(w, xargs, i); X# undef NXARGS X} SHAR_EOF fi exit 0 # End of shell archive -- Rick Richardson | Looking for FAX software for UNIX/386 ??? Ask About: |Mention PC Research,Inc.| FaxiX - UNIX Facsimile System (tm) |FAX# for uunet!pcrat!rick| FaxJet - HP LJ PCL to FAX (Send WP,Word,Pagemaker...)|Sample (201) 389-8963 | JetRoff - troff postprocessor for HP LaserJet and FAX|Output