// 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)); }
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); }