// Enables and sizes one of the scrollbars.
void ElementScroll::EnableScrollbar(Orientation orientation, float element_width)
{
	if (!scrollbars[orientation].enabled)
	{
		CreateScrollbar(orientation);
		scrollbars[orientation].element->SetProperty(VISIBILITY, "visible");
		scrollbars[orientation].enabled = true;
	}

	// Determine the size of the scrollbar.
	Box box;
	LayoutEngine::BuildBox(box, Vector2f(element_width, element_width), scrollbars[orientation].element);

	if (orientation == VERTICAL)
		scrollbars[orientation].size = box.GetSize(Box::MARGIN).x;
	if (orientation == HORIZONTAL)
	{
		if (box.GetSize().y < 0)
			scrollbars[orientation].size = box.GetCumulativeEdge(Box::CONTENT, Box::LEFT) +
										   box.GetCumulativeEdge(Box::CONTENT, Box::RIGHT) +
										   scrollbars[orientation].element->ResolveProperty(HEIGHT, element_width);
		else
			scrollbars[orientation].size = box.GetSize(Box::MARGIN).y;
	}
}
static XtGeometryResult
GeometryRequestPlusScrollbar(ViewportWidget w, Bool horizontal,
			     XtWidgetGeometry *request,
			     XtWidgetGeometry *reply_return)
{
    Widget sb;
    XtWidgetGeometry plusScrollbars;

    plusScrollbars = *request;
    if ((sb = w->viewport.horiz_bar) == NULL)
	sb = CreateScrollbar(w, horizontal);
    request->width += XtWidth(sb);
    request->height += XtHeight(sb);
    XtDestroyWidget(sb);
    return (XtMakeGeometryRequest((Widget)w, &plusScrollbars, reply_return));
}
示例#3
0
文件: ScrollByL.c 项目: aosm/X11apps
static void
Layout(Widget w)
{    
  ScrollByLineWidget sblw = (ScrollByLineWidget) w;
  Dimension width, height;
  Widget bar;
  Position bar_bw;

  CreateScrollbar(w);

/* 
 * For now always show the bar.
 */

  bar = sblw->scroll.bar;
  height = sblw->core.height;
  width = sblw->core.width;
  bar_bw = bar->core.border_width;

  /* Move child and v_bar to correct location. */

  if (sblw->scroll.use_right) {
    XtMoveWidget(bar, width - (bar->core.width + bar_bw), - bar_bw);
    sblw->scroll.offset = 0;
  }
  else {
    XtMoveWidget(bar, - bar_bw, - bar_bw);
    sblw->scroll.offset = bar->core.width + bar_bw;
  }

  /* resize the scrollbar to be the correct height or width. */

  XtResizeWidget(bar, bar->core.width, height, bar->core.border_width);

  SetThumbHeight(w);
  
  sblw->scroll.num_visible_lines = height / sblw->scroll.font_height + 1;
}
static XtGeometryResult
XawViewportGeometryManager(Widget child, XtWidgetGeometry *request,
			   XtWidgetGeometry *reply)
{
    ViewportWidget w = (ViewportWidget)child->core.parent;
    Bool rWidth = (request->request_mode & CWWidth) != 0;
    Bool rHeight = (request->request_mode & CWHeight) != 0;
    XtWidgetGeometry allowed;
    XtGeometryResult result;
    Bool reconfigured;
    Bool child_changed_size;
    unsigned int height_remaining;

    if (request->request_mode & XtCWQueryOnly)
	return (QueryGeometry(w, request, reply));

    if (child != w->viewport.child
	|| request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth)
	|| ((request->request_mode & CWBorderWidth)
	    && request->border_width > 0))
	return (XtGeometryNo);

    allowed = *request;

    reconfigured = GetGeometry((Widget)w,
				rWidth ? request->width : XtWidth(w),
				rHeight ? request->height : XtHeight(w));

    child_changed_size = (rWidth && XtWidth(child) != request->width) ||
			 (rHeight && XtHeight(child) != request->height);

    height_remaining = XtHeight(w);
    if (rWidth && XtWidth(w) != request->width) {
	if (w->viewport.allowhoriz && request->width > XtWidth(w)) {
	    /* horizontal scrollbar will be needed so possibly reduce height */
	    Widget bar;

	    if ((bar = w->viewport.horiz_bar) == NULL)
		bar = CreateScrollbar(w, True);
	    height_remaining -= XtHeight(bar) + XtBorderWidth(bar);
	    reconfigured = True;
	}
	else
	    allowed.width = XtWidth(w);
    }
    if (rHeight && height_remaining != request->height) {
	if (w->viewport.allowvert && request->height > height_remaining) {
	    /* vertical scrollbar will be needed, so possibly reduce width */
	    if (!w->viewport.allowhoriz || request->width < XtWidth(w)) {
		Widget bar;

		if ((bar = w->viewport.vert_bar) == NULL)
		    bar = CreateScrollbar(w, False);
		if (!rWidth) {
		    allowed.width = XtWidth(w);
		    allowed.request_mode |= CWWidth;
		}
		if (allowed.width  >  XtWidth(bar) + XtBorderWidth(bar))
		    allowed.width -= XtWidth(bar) + XtBorderWidth(bar);
		else
		    allowed.width = 1;
		reconfigured = True;
	    }
	}
	else
	    allowed.height = height_remaining;
    }

    if (allowed.width != request->width || allowed.height != request->height) {
	*reply = allowed;
	result = XtGeometryAlmost;
    }
    else {
	if (rWidth)
	    XtWidth(child) = request->width;
	if (rHeight)
	    XtHeight(child) = request->height;
	result = XtGeometryYes;
    }

    if (reconfigured || child_changed_size)
	ComputeLayout((Widget)w, False, result == XtGeometryYes);

    return (result);
}
/*
 * Function:
 *	ComputeWithForceBars
 *
 * Parameters:
 *	widget	    - viewport widget
 *	query	    - whether or not to query the child
 *	intended    - cache of the childs height is stored here
 *		      (used and returned)
 *	clip_width  - size of clip window (used and returned)
 *	clip_height - ""
 *
 * Description:
 *	Computes the layout give forcebars is set.
 */
static void
ComputeWithForceBars(Widget widget, Bool query, XtWidgetGeometry *intended,
		     int *clip_width, int *clip_height)
{
    ViewportWidget w = (ViewportWidget)widget;
    Widget child = w->viewport.child;
    XtWidgetGeometry preferred;

    /*
     * If forcebars then needs = allows = has
     * Thus if needsvert is set it MUST have a scrollbar
     */
    if (w->viewport.allowvert) {
	if (w->viewport.vert_bar == NULL)
	    w->viewport.vert_bar = CreateScrollbar(w, False);

	*clip_width -= XtWidth(w->viewport.vert_bar) +
		       XtBorderWidth(w->viewport.vert_bar);
    }

    if (w->viewport.allowhoriz) {
	if (w->viewport.horiz_bar == NULL)
	    w->viewport.horiz_bar = CreateScrollbar(w, True);

	*clip_height -= XtHeight(w->viewport.horiz_bar) +
			XtBorderWidth(w->viewport.horiz_bar);
    }

    AssignMax(*clip_width, 1);
    AssignMax(*clip_height, 1);

    if (!w->viewport.allowvert) {
	intended->height = *clip_height;
	intended->request_mode = CWHeight;
    }
    if (!w->viewport.allowhoriz) {
	intended->width = *clip_width;
	intended->request_mode = CWWidth;
    }

    if (query) {
	if (w->viewport.allowvert || w->viewport.allowhoriz) {
	    XtQueryGeometry(child, intended, &preferred);

	    if (!(intended->request_mode & CWWidth)) {
		if (preferred.request_mode & CWWidth)
		    intended->width = preferred.width;
		else
		    intended->width = XtWidth(child);
	    }

	    if (!(intended->request_mode & CWHeight)) {
		if (preferred.request_mode & CWHeight)
		    intended->height = preferred.height;
		else
		    intended->height = XtHeight(child);
	    }
	}
    }
    else {
	if (w->viewport.allowvert)
	    intended->height = XtHeight(child);
	if (w->viewport.allowhoriz)
	    intended->width = XtWidth(child);
    }

    if (*clip_width > (int)intended->width)
	intended->width = *clip_width;
    if (*clip_height > (int)intended->height)
	intended->height = *clip_height;
}
static void
ComputeLayout(Widget widget, Bool query, Bool destroy_scrollbars)
{
    ViewportWidget w = (ViewportWidget)widget;
    Widget child = w->viewport.child;
    Widget clip = w->viewport.clip;
    ViewportConstraints constraints =
	(ViewportConstraints)clip->core.constraints;
    Bool needshoriz, needsvert;
    int clip_width, clip_height;
    XtWidgetGeometry intended;

    if (child == NULL)
	return;

    clip_width = XtWidth(w);
    clip_height = XtHeight(w);
    intended.request_mode = CWBorderWidth;
    intended.border_width = 0;

    if (w->viewport.forcebars) {
	needsvert = w->viewport.allowvert;
	needshoriz = w->viewport.allowhoriz;
	ComputeWithForceBars(widget, query, &intended,
			     &clip_width, &clip_height);
    }
    else {
	Dimension prev_width, prev_height;
	XtGeometryMask prev_mode;
	XtWidgetGeometry preferred;

	needshoriz = needsvert = False;

	/*
	 * intended.{width,height} caches the eventual child dimensions,
	 * but we don't set the mode bits until after we decide that the
	 * child's preferences are not acceptable
	 */
	if (!w->viewport.allowhoriz)
	    intended.request_mode |= CWWidth;

	if (XtWidth(child) < clip_width)
	    intended.width = clip_width;
	else
	    intended.width = XtWidth(child);

	if (XtHeight(child) < clip_height)
	    intended.height = clip_height;
	else
	    intended.height = XtHeight(child);

	if (!w->viewport.allowvert)
	    intended.request_mode |= CWHeight;

	if (!query) {
	    preferred.width = XtWidth(child);
	    preferred.height = XtHeight(child);
	}
	do { /* while intended != prev  */
	    if (query) {
		(void)XtQueryGeometry(child, &intended, &preferred);
		if (!(preferred.request_mode & CWWidth))
		    preferred.width = intended.width;
		if (!(preferred.request_mode & CWHeight))
		    preferred.height = intended.height;
	    }
	    prev_width = intended.width;
	    prev_height = intended.height;
	    prev_mode = intended.request_mode;
	    /*
	     * note that having once decided to turn on either bar
	     * we'll not change our mind until we're next resized,
	     * thus avoiding potential oscillations
	     */
#define CheckHoriz() \
	    if (w->viewport.allowhoriz &&				\
		preferred.width > clip_width) {				\
		if (!needshoriz) {					\
		    Widget bar;						\
									\
		    needshoriz = True;					\
		    if ((bar = w->viewport.horiz_bar) == NULL)		\
			bar = CreateScrollbar(w, True);			\
		    clip_height -= XtHeight(bar) + XtBorderWidth(bar);	\
		    if (clip_height < 1)				\
			clip_height = 1;				\
		}							\
		intended.width = preferred.width;			\
	    }

	    CheckHoriz();
	    if (w->viewport.allowvert && preferred.height > clip_height) {
		if (!needsvert) {
		    Widget bar;
		    needsvert = True;
		    if ((bar = w->viewport.vert_bar) == NULL)
			bar = CreateScrollbar(w, False);
		    clip_width -= XtWidth(bar) + XtBorderWidth(bar);
		    if (clip_width < 1)
			clip_width = 1;
		    CheckHoriz();
		}
		intended.height = preferred.height;
	    }
	    if (!w->viewport.allowhoriz || preferred.width < clip_width) {
		intended.width = clip_width;
		intended.request_mode |= CWWidth;
	    }
	    if (!w->viewport.allowvert || preferred.height < clip_height) {
		intended.height = clip_height;
		intended.request_mode |= CWHeight;
	    }
	} while (intended.request_mode != prev_mode
		 || (intended.request_mode & CWWidth
		     && intended.width != prev_width)
		 || (intended.request_mode & CWHeight
		     && intended.height != prev_height));
    }

    if (XtIsRealized(clip))
	XRaiseWindow(XtDisplay(clip), XtWindow(clip));

    XtMoveWidget(clip,
		 needsvert ? w->viewport.useright ? 0 :
		 XtWidth(w->viewport.vert_bar)
		 + XtBorderWidth(w->viewport.vert_bar) : 0,
		 needshoriz ? w->viewport.usebottom ? 0 :
		 XtHeight(w->viewport.horiz_bar)
		 + XtBorderWidth(w->viewport.horiz_bar) : 0);
    XtResizeWidget(clip, clip_width, clip_height, 0);

    if (w->viewport.horiz_bar != NULL) {
	Widget bar = w->viewport.horiz_bar;

	if (!needshoriz) {
	    constraints->form.vert_base = NULL;
	    if (destroy_scrollbars) {
		XtDestroyWidget(bar);
		w->viewport.horiz_bar = NULL;
	    }
	}
	else {
	    int bw = XtBorderWidth(bar);

	    XtResizeWidget(bar, clip_width, XtHeight(bar), bw);
	    XtMoveWidget(bar,
			 needsvert && !w->viewport.useright
			 ? XtWidth(w->viewport.vert_bar) : -bw,
			 w->viewport.usebottom
			 ? XtHeight(w) - XtHeight(bar) - bw : -bw);
	    XtSetMappedWhenManaged(bar, True);
	}
    }

    if (w->viewport.vert_bar != NULL) {
	Widget bar = w->viewport.vert_bar;

	if (!needsvert)	{
	    constraints->form.horiz_base = NULL;
	    if (destroy_scrollbars) {
		XtDestroyWidget(bar);
		w->viewport.vert_bar = NULL;
	    }
	}
	else {
	    int bw = bar->core.border_width;

	    XtResizeWidget(bar, XtWidth(bar), clip_height, bw);
	    XtMoveWidget(bar,
			w->viewport.useright
			? XtWidth(w) - XtWidth(bar) - bw : -bw,
			needshoriz && !w->viewport.usebottom
			? XtHeight(w->viewport.horiz_bar) : -bw);
	   XtSetMappedWhenManaged(bar, True);
	}
    }

    if (child != NULL) {
	XtResizeWidget(child, intended.width, intended.height, 0);
	MoveChild(w, needshoriz ? XtX(child) : 0,	needsvert ? XtY(child) : 0);
    }

    SendReport (w, XawPRAll);
}
/*ARGSUSED*/
static void
XawViewportInitialize(Widget request, Widget cnew,
		      ArgList args, Cardinal *num_args)
{
    ViewportWidget w = (ViewportWidget)cnew;
    static Arg clip_args[8];
    Cardinal arg_cnt;
    Widget h_bar, v_bar;
    Dimension clip_height, clip_width;

    w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels */

    /*
     * Initialize all widget pointers to NULL
     */
    w->viewport.child = NULL;
    w->viewport.horiz_bar = w->viewport.vert_bar = NULL;

    /*
     * Create Clip Widget
     */
    arg_cnt = 0;
    XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None);	arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0);		arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft);		arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight);	arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop);		arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom);	arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNwidth, XtWidth(w));		arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNheight, XtHeight(w));	arg_cnt++;

    w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, cnew,
					     clip_args, arg_cnt);

    if (!w->viewport.forcebars)
	return;		 /* If we are not forcing the bars then we are done */

    if (w->viewport.allowhoriz)
	(void)CreateScrollbar(w, True);
    if (w->viewport.allowvert)
	(void)CreateScrollbar(w, False);

    h_bar = w->viewport.horiz_bar;
    v_bar = w->viewport.vert_bar;

    /*
     * Set the clip widget to the correct height
     */
    clip_width = XtWidth(w);
    clip_height = XtHeight(w);

    if (h_bar != NULL &&  XtWidth(w) > XtWidth(h_bar) + XtBorderWidth(h_bar))
	clip_width -= XtWidth(h_bar) + XtBorderWidth(h_bar);

    if (v_bar != NULL && XtHeight(w) > XtHeight(v_bar) + XtBorderWidth(v_bar))
	clip_height -= XtHeight(v_bar) + XtBorderWidth(v_bar);

    arg_cnt = 0;
    XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++;
    XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++;
    XtSetValues(w->viewport.clip, clip_args, arg_cnt);
}