Blame lib/Xm/ScroVis.c

Packit b099d7
/* $XConsortium: ScroVis.c /main/6 1995/09/19 23:07:44 cde-sun $ */
Packit b099d7
/*
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
 * 
Packit b099d7
 */
Packit b099d7
/*
Packit b099d7
 * HISTORY
Packit b099d7
 */
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#include <Xm/ScrolledWP.h>
Packit b099d7
#include <Xm/NavigatorT.h>
Packit b099d7
#include "ScrollFramTI.h"
Packit b099d7
#include "MessagesI.h"
Packit b099d7
#include "XmI.h"
Packit b099d7
Packit b099d7
#define SWMessage1      _XmMMsgScrollVis_0000 
Packit b099d7
Packit b099d7
/************************************************************************
Packit b099d7
 *									*
Packit b099d7
 * XmScrollVisible -  TraverseObscureCallback helper                    *
Packit b099d7
 *									*
Packit b099d7
 ************************************************************************/
Packit b099d7
void
Packit b099d7
XmScrollVisible(
Packit b099d7
		Widget      	scrw,
Packit b099d7
		Widget          wid,
Packit b099d7
		Dimension       hor_margin, 
Packit b099d7
		Dimension       ver_margin)
Packit b099d7
/*********************
Packit b099d7
 * A function that makes visible a unvisible or partially visible descendant 
Packit b099d7
 * of an AUTOMATIC scrolledwindow workwindow.
Packit b099d7
 *********************
Packit b099d7
 * - scrw is the ScrolledWindow whose workwindow act as the origin of the move.
Packit b099d7
 * - wid is the widget to be made visible.
Packit b099d7
 * - hor_margin, ver_margin are the margins between the widget in its new 
Packit b099d7
 *   position and the scrolledwindow clipwindow.
Packit b099d7
**********************/
Packit b099d7
{
Packit b099d7
    XmScrolledWindowWidget sw = (XmScrolledWindowWidget) scrw ;
Packit b099d7
    register 
Packit b099d7
    Position newx, newy,      /* new workwindow position */
Packit b099d7
             wx, wy  ;        /* current workwindow position */
Packit b099d7
    register 
Packit b099d7
    unsigned short tw, th,         /* widget sizes */
Packit b099d7
              cw, ch ;        /* clipwindow sizes */
Packit b099d7
    Position dx, dy ;         /* position inside the workwindow */
Packit b099d7
    Position src_x, src_y, dst_x, dst_y ;
Packit b099d7
    Widget w ;
Packit b099d7
    XmScrolledWindowConstraint swc;
Packit b099d7
    XmNavigatorDataRec nav_data ;
Packit b099d7
    _XmWidgetToAppContext(scrw);
Packit b099d7
Packit b099d7
    _XmAppLock(app);
Packit b099d7
    /* check param */
Packit b099d7
    if (!((scrw) && (XmIsScrolledWindow(scrw)) &&
Packit b099d7
	  (sw->swindow.ScrollPolicy == XmAUTOMATIC))) {
Packit b099d7
	XmeWarning(scrw, SWMessage1);
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return ;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* loop up in search for a "workwindow" */
Packit b099d7
    w = wid;
Packit b099d7
    while (w && (XtParent(w) != (Widget) sw->swindow.ClipWindow))
Packit b099d7
      w = XtParent(w);
Packit b099d7
    if (!w) {
Packit b099d7
	XmeWarning(scrw, SWMessage1);
Packit b099d7
	_XmAppUnlock(app);
Packit b099d7
	return ;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* w is the potentially scrollable ascendant of wid that needs to 
Packit b099d7
       be scrolled, its parent is the clip window */
Packit b099d7
    /* In the new scheme, w might not be able to scroll at all,
Packit b099d7
       or even in the direction the margins point to. There is
Packit b099d7
       nothing much we can do about that except document that
Packit b099d7
       traversing to an unvisible kid of unscrollable workwindow will
Packit b099d7
       not scroll it, resulting in unvisible focus widget. We could
Packit b099d7
       check for NO_SCROLL in w, but since we cannot check for SCROLL_HOR
Packit b099d7
       or SCROLL_VERT - depend on the traversal layout - I'd rather do 
Packit b099d7
       nothing */
Packit b099d7
Packit b099d7
    /* we need to get the position of wid relative to w, 
Packit b099d7
       so we use 2 XtTranslateCoords */
Packit b099d7
    
Packit b099d7
    XtTranslateCoords(wid, 0, 0, &src_x, &src_y);
Packit b099d7
    XtTranslateCoords(w, 0, 0, &dst_x, &dst_y);
Packit b099d7
    dx = src_x - dst_x ;
Packit b099d7
    dy = src_y - dst_y ;
Packit b099d7
Packit b099d7
    swc = GetSWConstraint(w);
Packit b099d7
   
Packit b099d7
    /* get the other positions and sizes */
Packit b099d7
    cw = XtWidth((Widget) sw->swindow.ClipWindow) ;
Packit b099d7
    ch = XtHeight((Widget) sw->swindow.ClipWindow) ;
Packit b099d7
    wx = swc->orig_x - XtX(w) ;  
Packit b099d7
    wy = swc->orig_y - XtY(w) ; /* both always positive */
Packit b099d7
    tw = XtWidth(wid) ;
Packit b099d7
    th = XtHeight(wid) ;
Packit b099d7
    
Packit b099d7
    /* find out the zone where the widget lies and set newx,newy (neg) for
Packit b099d7
       the workw */
Packit b099d7
    /* if the widget is bigger than the clipwindow, we put it on
Packit b099d7
       the left, top or top/left, depending on the zone it was */
Packit b099d7
Packit b099d7
    if (dy < wy) {                                       /* North */
Packit b099d7
	newy = dy - (Position)ver_margin ;      /* stuck it on top + margin */
Packit b099d7
    } else 
Packit b099d7
    if ((dy + th) <= (ch - XtY(w))) {
Packit b099d7
	newy = wy ;               /* in the middle : don't move y */
Packit b099d7
    } else {                                             /* South */
Packit b099d7
	if (th > ch)
Packit b099d7
	    newy = dy - (Position)ver_margin ; /* stuck it on top if too big */
Packit b099d7
	else
Packit b099d7
	    newy = swc->orig_y + dy - ch + th + (Position)ver_margin;
Packit b099d7
    } 
Packit b099d7
	
Packit b099d7
    if (dx < wx) {                              /* West */
Packit b099d7
	newx = dx - (Position)hor_margin ; /* stuck it on left + margin */
Packit b099d7
    } else
Packit b099d7
    if ((dx + tw) <= (cw - XtX(w))) {
Packit b099d7
	newx = wx ;  /* in the middle : don't move x */
Packit b099d7
    } else {                                     /* East */
Packit b099d7
	if (tw > cw)
Packit b099d7
	    newx = dx - (Position)hor_margin ; /* stuck it on left if too big */
Packit b099d7
	else
Packit b099d7
	    newx = swc->orig_x + dx - cw + tw + (Position)hor_margin;
Packit b099d7
    } 
Packit b099d7
Packit b099d7
    /* a last check */
Packit b099d7
    if (newx > sw->swindow.hmax - sw->swindow.hExtent) 
Packit b099d7
	newx = sw->swindow.hmax - sw->swindow.hExtent;
Packit b099d7
    if (newy > sw->swindow.vmax - sw->swindow.vExtent) 
Packit b099d7
	newy = sw->swindow.vmax - sw->swindow.vExtent;
Packit b099d7
    if (newx < sw->swindow.hmin) newx =  sw->swindow.hmin ;
Packit b099d7
    if (newy < sw->swindow.vmin) newy =  sw->swindow.vmin ;
Packit b099d7
Packit b099d7
    nav_data.valueMask = NavValue ;
Packit b099d7
    nav_data.value.x = newx ;
Packit b099d7
    nav_data.value.y = newy ;
Packit b099d7
    nav_data.dimMask = NavigDimensionX|NavigDimensionY ;
Packit b099d7
    _XmSFUpdateNavigatorsValue((Widget)sw, &nav_data, True);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
}