[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference bulova::decw_jan-89_to_nov-90

Title:DECWINDOWS 26-JAN-89 to 29-NOV-90
Notice:See 1639.0 for VMS V5.3 kit; 2043.0 for 5.4 IFT kit
Moderator:STAR::VATNE
Created:Mon Oct 30 1989
Last Modified:Mon Dec 31 1990
Last Successful Update:Fri Jun 06 1997
Number of topics:3726
Total number of notes:19516

2131.0. "Can't get scroll window layed out" by EXLIB::DLUGOSZ (Open foot, Insert Mouth) Wed Jan 24 1990 15:41

    According to the documentation that I have available you scroll
    the work area of a scroll window by moving that work area widget
    with respect to its parent (the scroll window).
                        
    I've been trying to set up a scroll window that has as it's children
    a window widget and two scroll bars. No matter what I've tryed 
    (including looking through 5 notes conferences) I can't get the
    widgets layed out in a way that works.
    
    If I make the window widget larger than the scroll window (which
    seems logical since I wouldn't need to scroll something that was
    the same size or smaller than the scroll window) it overlays the
    scroll bars.
    
    I thought that the scroll window behaved similar to the main window
    widget in managing its children - i.e., when you specify a height
    and width of a main widget with menu bars, scroll bars, etc you
    are actually specifying the size of it's work area. Now matter 
    how large you make the work area widget it doesn't overlay the
    scroll bars.....
    
    
    Any ideas?
    
    Ron
T.RTitleUserPersonal
Name
DateLines
2131.1possibly need to "set areas"...RTL::OBRYANWhen in doubt, let the user decide.Thu Jan 25 1990 00:07424
re:.0
>    If I make the window widget larger than the scroll window ...
>    ...it overlays the scroll bars.
    
>    I thought that the scroll window behaved similar to the main window
>    widget in managing its children - i.e., when you specify a height
>    and width of a main widget with menu bars, scroll bars, etc you
>    are actually specifying the size of it's work area. Now matter 
>    how large you make the work area widget it doesn't overlay the
>    scroll bars.....
Indeed, the scroll window is in charge of preventing this situation, i.e.
it places its designated children in the proper places and sizes them.
In your case, it sounds as if the scroll window doesn't know which of its
children is which.  The scroll window provides 3 resources which allows
you to designate which child is which.  There is a utility routine called
(something like) ScrollWindowSetAreas which allows you to tell the scroll
window which child is the vertical/horizontal scroll bars and the work area.
(You can set them via SetValues, but less efficiently.)  Note that this
setting is provided in UIL/DRM via the scroll_window arguments in the example
code below.  I believe the reason you don't see the same behavior in main
windows is that they are smart enough to set their own "areas".  (There is
a similar "set areas" routine for main windows (MainWindowSetAreas?).)

Here is a UIL example.  (I have included a routine at the end which properly
causes the work area to scroll for all scroll bar callback reasons.)

! Main window which uses a scroll_window as its work area.
    test_MnWind	: main_window 
    {
	arguments
	{
	    arguments gnc_main_window_args;
	    x = k_tst_test_MnWind_x;
	    y = k_tst_test_MnWind_y;
	    width = k_tst_test_MnWind_wid;
	    height = k_tst_test_MnWind_hei;
	    main_menu_bar = menu_bar test_MenuBar;		!*** Set Main
	    main_work_window = scroll_window work_ScrWind;	!*** Areas
	};
	controls
	{
	    menu_bar		test_MenuBar;			!***
	    scroll_window	work_ScrWind;			!***
	};
	callbacks
	{
	    help = procedure tst_help_proc (k_tst_test_MnWind_key);
	    create = procedure tst_create_proc (k_tst_test_MnWind);
	    focus = procedure tst_focus_proc (k_tst_test_MnWind);
	}; !callbacks
    }; ! test_MnWind

    work_ScrWind	: scroll_window 
    {
	arguments
	{
	    arguments gnc_scroll_window_args;
	    width = k_tst_work_ScrWind_wid;
	    height = k_tst_work_ScrWind_hei;
	    horizontal_scroll_bar = scroll_bar work_h_ScrBar;	!** Set Areas
	    vertical_scroll_bar = scroll_bar work_v_ScrBar;	!**
	    work_window = window work_area_window;		!**
	};
	controls
	{
	    scroll_bar	work_h_ScrBar;				!**
	    scroll_bar	work_v_ScrBar;				!**
	    window	work_area_window;			!**
	};
	callbacks
	{
	    help = procedure tst_help_proc (k_tst_work_ScrWind_key);
	    create = procedure tst_create_proc (k_tst_work_ScrWind);
	}; !callbacks
    }; ! work_ScrWind

    work_h_ScrBar	: scroll_bar 
    {
	arguments
	{
	    arguments gnc_scroll_bar_args;
	    orientation = DwtOrientationHorizontal;
	};
	callbacks
	{
	    help = procedure tst_help_proc (k_tst_work_h_ScrBar_key);
	    create = procedure tst_create_proc (k_tst_work_h_ScrBar);

	    drag = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    value_changed = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    page_dec = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    page_inc = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    to_bottom = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    to_top = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    unit_dec = procedure tst_scroller_proc (k_tst_work_h_ScrBar);
	    unit_inc = procedure tst_scroller_proc (k_tst_work_h_ScrBar);

	}; !callbacks
    }; ! work_h_ScrBar

    work_v_ScrBar	: scroll_bar 
    {
	arguments
	{
	    arguments gnc_scroll_bar_args;
	    orientation = DwtOrientationVertical;
	};
	callbacks
	{
	    help = procedure tst_help_proc (k_tst_work_v_ScrBar_key);
	    create = procedure tst_create_proc (k_tst_work_v_ScrBar);

	    drag = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    value_changed = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    page_dec = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    page_inc = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    to_bottom = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    to_top = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    unit_dec = procedure tst_scroller_proc (k_tst_work_v_ScrBar);
	    unit_inc = procedure tst_scroller_proc (k_tst_work_v_ScrBar);

	}; !callbacks
    }; ! work_v_ScrBar

    work_area_window	: window
    {
	arguments
	{
	    ...
	};
	callbacks
	{
	    ...
	}; !callbacks
    }; ! work_area_window

------------------------------------------
Here is a segment from the tst_scroller routine, which calls the generic
scroll work area routine.

void tst_scroller_proc ( a_object, al_object_tag, a_cb_struct )
/*==========================================================================
** This callback routine is called for the reason(s):	value_changed,
**	page_dec, page_inc, to_bottom, to_top, unit_dec, unit_inc, drag.
**
** Parameters:*/
    Widget	a_object;
    int		*al_object_tag;
    DwtScrollBarCallbackStruct	*a_cb_struct;
/*
**-------------------------------------------------------------------------*/
{

    switch ( *al_object_tag )
	{
	case k_tst_work_h_ScrBar:
	case k_tst_work_v_ScrBar:
	    {
	    util_scroll_work_area ( a_object, a_cb_struct,
		ra_object_ids[k_tst_work_area_window] ); /*widget id-work area*/
	    break;
	    };

...

The generic work area scroll routine:

int  util_scroll_work_area ( a_scroll_bar , callbackdata ,  a_work_area )
/*==============================================================================
**  This routine performs the movement of the work area widget relative to
**	it's parent scroll_window, performing the user's scroll request from
**	the scroll bar.  It works on any of the 8 callback reasons currently
**	returned by scroll_bars (drag, value_change, to_top, to_bottom,
**	page_inc, page_dec, unit_inc, unit_dec).
**  The actions performed by this routine are based on the V1/V2 behavior of
**	the toolkit scroll_window, relying on its partial intelligence with
**	respect to scroll_bars and work_area widgets.  Future enhancements to
**	scroll_window may eliminate the need for some (or all) of the actions
**	in this routine.
**  Assumptions:
**	- The application wishes the scroll to be performed by simply changing
**	  the x or y coordinate of the work area widget (with respect to its
**	  parent, the scroll_window widget.)
**	- The work_area widget is not able to be scrolled completely out of the
**	  parent (i.e. the some portion (or all) of the work_area widget fills
**	  scroll_window's viewable space.)
**	- The scroll_bar's "long" dimension is a valid measure of the viewable
**	  area.
**	- The scroll_bar's min_value is always less than max_value.  (Both
**	  can be negative.)
**
** Parameters:
*/
    Widget	a_scroll_bar;		/* The scroll_bar's widget id	      */
    DwtScrollBarCallbackStruct *callbackdata; /* Structure returned to a      */
					/*  scroll_bar's callback routine     */
    Widget	a_work_area;		/* Widget id of the target widget     */
/*
**  Fields:  reason, *event, value(int), pixel
**----------------------------------------------------------------------------*/
{
int  l_minval=0, l_maxval=0, l_shown=0, l_unit_inc=0, l_val=0, l_page_inc=0;
int  l_value_range, l_new_val=0;
unsigned char	v_orientation = (char) 0;

Dimension
	w_scrbar_wid=0, w_scrbar_hei=0,
	w_work_area_wid=0, w_work_area_hei=0;
Position
	w_work_area_x=0, w_work_area_y=0;

Arg r_scrbar_args[]= {
	{DwtNminValue,&l_minval},
	{DwtNmaxValue,&l_maxval},
	{DwtNwidth,&w_scrbar_wid},
	{DwtNheight,&w_scrbar_hei},
	{DwtNvalue,&l_val},
	{DwtNorientation,&v_orientation},
	{DwtNinc,&l_unit_inc},
	{DwtNpageInc,&l_page_inc},
	{DwtNshown,&l_shown} };
#define k_scrbar_args_size array_size(r_scrbar_args)

Arg r_work_area_args[]= {
	{DwtNwidth,&w_work_area_wid},
	{DwtNheight,&w_work_area_hei},
	{DwtNx,&w_work_area_x},
	{DwtNy,&w_work_area_y} };
#define k_work_area_args_size array_size(r_work_area_args)

Arg r_work_area_set_args[1]= {{DwtNy,0}};

/*  The value returned by scroll_bar in the callback structure is a number
between 'minvalue' and 'maxvalue - shown'.  Therefore, the (absolute) value
number (minus the minvalue) divided by this range is the percentage position
of the underlying work area relative to the scroll_bar.  The range of
scrollability of the work_area in a particular (x or y) dimension is:
	'linear dimension of work area - linear dimension of scroll_bar'.
(This is assuming that the work_area widget is not permitted to scroll out of
the parent's area of viewability, that in fact work_area's border will never
be visible within that area unless it is smaller than the viewable area.)
The linear scroll_bar dimension and the 'area of viewability' in the parent
widget are assumed to be identical (i.e. there are no gaps around the scroll
bar.)  As such, the parent [scroll_window] need not be involved in the
calculations at all.

Summary:
	% position = abs(value-min)/abs(max-min-shown)
	x_range = 0  to  -(work_area_wid - scrbar_wid)
	y_range = 0  to  -(work_area_hei - scrbar_hei)
Therefore, either x OR y of the work_area widget will be recomputed.
	x = - (% position) * (x_range)
	y = - (% position) * (y_range)
	x = - (abs(value-min) * (work_area_wid - scr_wid))/abs(max-min-shown)
	y = - (abs(value-min) * (work_area_hei - scr_hei))/abs(max-min-shown)
*/
    /* Get the values from the two relevant widgets in the system.	*/
    /*									*/ 
    XtGetValues(a_scroll_bar,r_scrbar_args,k_scrbar_args_size);
    XtGetValues(a_work_area,r_work_area_args,k_work_area_args_size);

    /* Compute the breadth of 'value' span for this scroll bar. */
    l_value_range = l_maxval - l_minval - l_shown;

    switch (callbackdata->reason)
    {
	case DwtCRUnitInc:
	case DwtCRUnitDec:
	case DwtCRPageInc:
	case DwtCRPageDec:
	case DwtCRValueChanged:
	case DwtCRDrag:
	{
	    if (v_orientation == DwtOrientationHorizontal)
		{
		if (l_value_range <= 0)	/* Area not scrollable, it fills the */
		    w_work_area_x = 0;	/* viewable portion of scroll_window */
		else
		    w_work_area_x = - abs(
			( (callbackdata->value - l_minval) *
			  (int)(w_work_area_wid - w_scrbar_wid) ) /
				l_value_range );

		XtSetArg(r_work_area_set_args[0], DwtNx, w_work_area_x);
		}

	    else  /* v_orientation == DwtOrientationVertical */
		{
		if (l_value_range <= 0)	/* Area not scrollable, it fills the */
		    w_work_area_y = 0;	/* viewable portion of scroll_window */
		else
		    w_work_area_y = - abs(
			( (callbackdata->value - l_minval) *
			  (int)(w_work_area_hei - w_scrbar_hei) ) /
				l_value_range );

		XtSetArg(r_work_area_set_args[0], DwtNy, w_work_area_y);
		};

	    XtSetValues(a_work_area,r_work_area_set_args,1);
	    break;
	};	/* case of Incs/Decs/Drag/ValChanged  */

	case DwtCRToTop:
	{
	    /* For top/bottom, both repositioning the work area AND changing
		the slider position must be done.  (Slider is automatic
		for the 'other' callback reasons.) */

	    /* For top/bottom, the 'value' resource is not used in the
		calculation of movement of the work area widget.  The major
		reason is that 'pixel' is a much more precise measure of what
		portion of the viewing area the user wishes to have moved to
		the top or bottom of the scroll_window.  Movement is simply a
		matter of adding/subtracting the pixel value to x/y.  Secondly,
		the 'value' number may have a "many to one" relationship with
		screen coordinate space, meaning that the work area could be
		moved a larger amount rather than the visible amount.  Also,
		the 'value' number is no longer restricted to the minValue and
		maxValue range since the click can occur in any part of the
		scroll_bar, not just the scroll-slider region.  Determining
		'bounds' using the 'value' becomes problematic. */
		
	    if (v_orientation == DwtOrientationHorizontal)
		{
		w_work_area_x = w_work_area_x - callbackdata->pixel;
		if (w_work_area_x < (w_scrbar_wid - w_work_area_wid))
			  w_work_area_x = w_scrbar_wid - w_work_area_wid;
		XtSetArg(r_work_area_set_args[0], DwtNx, w_work_area_x);

		/* Set the 'value' on the scroll_bar to get it to reposition
		   slider.  (The slider position is determined by 'value'.)
		   First check if the work area is even scrollable (i.e.
		   the work area is smaller or the same size as scroll_bar). */
		if (w_scrbar_wid >= w_work_area_wid)
		    l_new_val = l_minval;
		else
		    l_new_val = (((int)w_work_area_x * l_value_range)
			/ (int)(w_scrbar_wid - w_work_area_wid) ) + l_minval;
		}
	    else  /* v_orientation == DwtOrientationVertical */
		{
		w_work_area_y = w_work_area_y - callbackdata->pixel;
		if (w_work_area_y < (w_scrbar_hei - w_work_area_hei))
			  w_work_area_y = w_scrbar_hei - w_work_area_hei;
		XtSetArg(r_work_area_set_args[0], DwtNy, w_work_area_y);

		/* Set the 'value' on the scroll_bar to get it to reposition
		   slider.  (The slider position is determined by 'value'.) */
		if (w_scrbar_hei >= w_work_area_hei)
		    l_new_val = l_minval;
		else
		    l_new_val = (((int)w_work_area_y * l_value_range)
			/ (int)(w_scrbar_hei - w_work_area_hei) ) + l_minval;
		};

	    XtSetValues(a_work_area,r_work_area_set_args,1);

	    /* Set the scroll slider to its proper position.  If there will be
		no change in the visible slider (value), don't bother to make
		the call.  */
	    if (l_val != l_new_val)
		{
		DwtScrollBarSetSlider(a_scroll_bar,l_new_val,l_shown,
			l_unit_inc,l_page_inc,FALSE);
		};

	    break;
	};

	case DwtCRToBottom:
	{
	    if (v_orientation == DwtOrientationHorizontal)
		{
		w_work_area_x = w_work_area_x +
			(w_scrbar_wid - callbackdata->pixel - 1);
		if (w_work_area_x > 0)  w_work_area_x = 0;
		XtSetArg(r_work_area_set_args[0], DwtNx, w_work_area_x);

		/* Set the 'value' on the scroll_bar to get it to reposition
		   slider.  (The slider position is determined by 'value'.) */
		if (w_scrbar_wid >= w_work_area_wid)
		    l_new_val = l_minval;
		else
		    l_new_val = (((int)w_work_area_x * l_value_range)
			/ (int)(w_scrbar_wid - w_work_area_wid) ) + l_minval;
		}
	    else  /* v_orientation == DwtOrientationVertical */
		{
		w_work_area_y = w_work_area_y +
			(w_scrbar_hei - callbackdata->pixel - 1);
		if (w_work_area_y > 0)  w_work_area_y = 0;
		XtSetArg(r_work_area_set_args[0], DwtNy, w_work_area_y);

		/* Set the 'value' on the scroll_bar to get it to reposition
		   slider.  (The slider position is determined by 'value'.) */
		if (w_scrbar_hei >= w_work_area_hei)
		    l_new_val = l_minval;
		else
		    l_new_val = ( ((int)w_work_area_y * l_value_range)
			/ (int)(w_scrbar_hei - w_work_area_hei) ) + l_minval;
		};

	    XtSetValues(a_work_area,r_work_area_set_args,1);

	    /* Set the scroll slider to its proper position.  If there will be
		no change in the visible slider (value), don't bother to make
		the call.  */
	    if (l_val != l_new_val)
		{
		DwtScrollBarSetSlider(a_scroll_bar,l_new_val,l_shown,
			l_unit_inc,l_page_inc,FALSE);
		};

	    break;
	};

    };	/* end of switch */

    return 1;

};	/* end of util_scroll_work_area */

2131.2That's it - ThanksEXLIB::DLUGOSZOpen foot, Insert MouthThu Jan 25 1990 10:077
    That did it. My mistake was in assuming that the scroll window had
    as much smarts as the main window. 
    
    
    Thanks for your help.
    
    Ron