/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /*----------------------------------------------------------------------*/ /* */ /* Name: */ /* Description: Xfe widgets geometry utilities. */ /* Author: Ramiro Estrugo */ /* */ /*----------------------------------------------------------------------*/ #include #include #include #if 0 #ifdef DEBUG_ramiro #define DEBUG_DIMENSIONS 1 #endif #endif /*----------------------------------------------------------------------*/ /* */ /* Access functions */ /* */ /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeBorderWidth(Widget w) { assert( w != NULL ); #if DEBUG_DIMENSIONS { Dimension border_width = (Dimension) XfeGetValue(w,XmNborderWidth); assert( border_width == _XfeBorderWidth(w) ); } #endif return _XfeBorderWidth(w); } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeWidth(Widget w) { assert( w != NULL ); #if DEBUG_DIMENSIONS { Dimension width = (Dimension) XfeGetValue(w,XmNwidth); assert( width == _XfeWidth(w) ); } #endif return _XfeWidth(w); } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeHeight(Widget w) { assert( w != NULL ); #if DEBUG_DIMENSIONS { Dimension height = (Dimension) XfeGetValue(w,XmNheight); assert( height == _XfeHeight(w) ); } #endif return _XfeHeight(w); } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeScreenWidth(Widget w) { assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } return DisplayWidth(XtDisplay(w),XScreenNumberOfScreen(_XfeScreen(w))); } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeScreenHeight(Widget w) { assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } return DisplayHeight(XtDisplay(w),XScreenNumberOfScreen(_XfeScreen(w))); } /*----------------------------------------------------------------------*/ /* extern */ Position XfeX(Widget w) { assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } return _XfeX(w); } /*----------------------------------------------------------------------*/ /* extern */ Position XfeY(Widget w) { assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } return _XfeY(w); } /*----------------------------------------------------------------------*/ /* extern */ Position XfeRootX(Widget w) { Position root_x; assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } XtTranslateCoords(w,0,0,&root_x,NULL); return root_x; } /*----------------------------------------------------------------------*/ /* extern */ Position XfeRootY(Widget w) { Position root_y; assert( _XfeIsAlive(w) ); if (!_XfeIsAlive(w)) { return 0; } XtTranslateCoords(w,0,0,NULL,&root_y); return root_y; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* */ /* Biggest, widest and tallest functions */ /* */ /*----------------------------------------------------------------------*/ /* extern */ Widget XfeBiggestWidget(Boolean horizontal,WidgetList widgets,Cardinal n) { Dimension biggest_dim = 0; Dimension dim; Widget max_widget = NULL; Widget widget; Cardinal i; assert( widgets != NULL ); if (!widgets) { return NULL; } for (i = 0; i < n; i++) { widget = widgets[i]; assert( _XfeIsAlive(widget) ); dim = (horizontal ? _XfeWidth(widget) : _XfeHeight(widget)); if (dim > biggest_dim) { biggest_dim = dim; max_widget = widget; } } return max_widget; } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeVaGetWidestWidget(Widget w, ...) { va_list vargs; Widget current; Dimension width; Dimension widest_width; /* * Get the first widget's width * (because of the way var args works * we have to start the loop at the second widget) */ widest_width = _XfeWidth(w); /* * Get the widest width */ va_start (vargs, w); while ((current = va_arg (vargs, Widget))) { width = _XfeWidth(current); if (width > widest_width) { widest_width = width; } } va_end (vargs); return widest_width; } /*----------------------------------------------------------------------*/ /* extern */ Dimension XfeVaGetTallestWidget(Widget w, ...) { va_list vargs; Widget current; Dimension height; Dimension widest_height; /* * Get the first widget's height * (because of the way var args works * we have to start the loop at the second widget) */ widest_height = _XfeHeight(w); /* * Get the widest height */ va_start (vargs, w); while ((current = va_arg (vargs, Widget))) { height = _XfeHeight(current); if (height > widest_height) { widest_height = height; } } va_end (vargs); return widest_height; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* */ /* Misc */ /* */ /*----------------------------------------------------------------------*/ /* extern */ Dimension _XfeHeightCenter(Widget one,Widget two) { assert( one != NULL ); assert( _XfeIsAlive(one) ); assert( two != NULL ); assert( _XfeIsAlive(two) ); return (_XfeHeight(one) > _XfeHeight(two)) ? ((_XfeHeight(one) - _XfeHeight(two)) / 2) : 0; } /*----------------------------------------------------------------------*/ /* extern */ Dimension _XfeWidthCenter(Widget one,Widget two) { assert( one != NULL ); assert( _XfeIsAlive(one) ); assert( two != NULL ); assert( _XfeIsAlive(two) ); return (_XfeWidth(one) > _XfeWidth(two)) ? ((_XfeWidth(one) - _XfeWidth(two)) / 2) : 0; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* */ /* Geometry */ /* */ /*----------------------------------------------------------------------*/ /* extern */ void _XfeConfigureWidget(Widget w,int x,int y,int width,int height) { assert( _XfeIsAlive(w) ); #if 0 printf("_XfeConfigureWidget(%s,%d,%d,%d,%d)\n",XtName(w),x,y,width,height); #endif /* The dimensions could be negative since we use ints. This would * indicate that the caller is passing in bad dimension values. * * These assertions help me find such problems. */ #if 0 #ifdef DEBUG_ramiro assert( width >= 0 ); assert( height >= 0 ); #endif #endif /* Ignore this request if width or height are 0. * * The right thing would be for the above asserts to catch 0 as well. * * The problem is that the dynamic nature of manager widgets, sometimes * causes them to resize their children to be tiny (zero). * * Well, its not really a "problem". Ignoring it is seems like a * reasonable thing to do for now. */ if (!width || !height) { return; } /* Make sure the positions and dimensions are different */ if ((_XfeX(w) == x) && (_XfeY(w) == y) && (_XfeWidth(w) == width) && (_XfeHeight(w) == height)) { return; } /* Configure XfePrimitive class */ if (XfeIsPrimitive(w)) { Boolean use_preferred_height; Boolean use_preferred_width; use_preferred_width = _XfeUsePreferredWidth(w); use_preferred_height = _XfeUsePreferredHeight(w); _XfeUsePreferredWidth(w) = False; _XfeUsePreferredHeight(w) = False; XtConfigureWidget(w,x,y,width,height,_XfeBorderWidth(w)); _XfeUsePreferredWidth(w) = use_preferred_width; _XfeUsePreferredHeight(w) = use_preferred_height; } /* Configure XfeManager class */ else if (XfeIsManager(w)) { Boolean use_preferred_height; Boolean use_preferred_width; _XfemOldWidth(w) = _XfeWidth(w); _XfemOldHeight(w) = _XfeHeight(w); use_preferred_width = _XfemUsePreferredWidth(w); use_preferred_height = _XfemUsePreferredHeight(w); _XfemUsePreferredWidth(w) = False; _XfemUsePreferredHeight(w) = False; XtConfigureWidget(w,x,y,width,height,_XfeBorderWidth(w)); _XfemUsePreferredWidth(w) = use_preferred_width; _XfemUsePreferredHeight(w) = use_preferred_height; } /* Configure any other class */ else { _XmConfigureObject(w,x,y,width,height,_XfeBorderWidth(w)); } } /*----------------------------------------------------------------------*/ /* extern */ void _XfeConfigureOrHideWidget(Widget w,int x,int y,int width,int height) { assert( _XfeIsAlive(w) ); /* Make sure the widget is alive */ if (!_XfeIsAlive(w)) { return; } /* Make sure the positions and dimensions are different */ if ((_XfeX(w) == x) && (_XfeY(w) == y) && (_XfeWidth(w) == width) && (_XfeHeight(w) == height)) { return; } /* Hide the widget if its dimensions are less thanb zero */ if (!width || !height) { _XfeSetMappedWhenManaged(w,False); return; } _XfeConfigureWidget(w,x,y,width,height); /* Show the widget */ _XfeSetMappedWhenManaged(w,True); } /*----------------------------------------------------------------------*/ /* extern */ void _XfeResizeWidget(Widget w,int width,int height) { assert( _XfeIsAlive(w) ); #if 0 printf("_XfeResizeWidget(%s,%d,%d)\n",XtName(w),width,height); #endif #if 0 assert( width > 0 ); assert( height > 0 ); #endif /* Ignore this request if width or height are 0 */ if (!width || !height) { return; } /* Make sure the dimension are different */ if ((_XfeWidth(w) == width) && (_XfeHeight(w) == height)) { return; } _XfeConfigureWidget(w,_XfeX(w),_XfeY(w),width,height); } /*----------------------------------------------------------------------*/ /* extern */ void _XfeMoveWidget(Widget w,int x,int y) { /* Make sure the widget is alive */ if (!_XfeIsAlive(w)) { return; } #if 0 printf("_XfeMoveWidget(%s,%d,%d)\n",XtName(w),width,height); #endif #if 0 assert( x >= 0 ); assert( y >= 0 ); #endif /* Make sure the positions are different */ if ((_XfeX(w) == x) && (_XfeY(w) == y)) { return; } /* Configure XfePrimitive or XfeManager classes */ if (XfeIsPrimitive(w) || XfeIsManager(w)) { XtMoveWidget(w,x,y); } /* Configure any other class */ else { _XmMoveObject(w,x,y); } } /*----------------------------------------------------------------------*/ /* extern */ void _XfePreferredGeometry(Widget w,Dimension *width_out,Dimension *height_out) { Dimension width; Dimension height; assert( _XfeIsAlive(w) ); if (XfeIsPrimitive(w)) { width = _XfePreferredWidth(w); height = _XfePreferredHeight(w); } else if (XfeIsManager(w)) { width = _XfemPreferredWidth(w); height = _XfemPreferredHeight(w); } else { XtWidgetGeometry reply; XtQueryGeometry(w,NULL,&reply); if (reply.request_mode & CWWidth) { width = reply.width; } else { width = _XfeWidth(w); } if (reply.request_mode & CWHeight) { height = reply.height; } else { height = _XfeHeight(w); } } if (width_out) { *width_out = width; } if (height_out) { *height_out = height; } } /*----------------------------------------------------------------------*/ /* * This function should be really clever and deal with all the * craziness of Xt geometry management. This will probably happen * on a case by case basis. As it stands, it works with the xfe * widgets, but I suspect it will have to be amended for more * sophisticated geometry magic. * * The basic assumption here is that geometry requests always * return YES as is in _XfeLiberalGeometryManager(). */ /* extern */ Boolean _XfeMakeGeometryRequest(Widget w,Dimension width,Dimension height) { XtGeometryResult request_result; XtWidgetGeometry request; Boolean result = False; assert( _XfeIsAlive(w) ); request.request_mode = 0; /* Request a width change */ if (width != _XfeWidth(w)) { request.width = width; request.request_mode |= CWWidth; } /* Request a height change */ if (height != _XfeHeight(w)) { request.height = height; request.request_mode |= CWHeight; } /* WTF */ if (request.request_mode == 0) { return False; } /* Make the request. */ request_result = _XmMakeGeometryRequest(w,&request); /* Adjust geometry accordingly */ if (request_result == XtGeometryYes) { result = True; } else if(request_result == XtGeometryNo) { result = False; } else if(request_result == XtGeometryAlmost) { result = False; } return result; } /*----------------------------------------------------------------------*/ /* extern */ XtGeometryResult _XfeLiberalGeometryManager(Widget child, XtWidgetGeometry * request, XtWidgetGeometry * reply) { Widget w = XtParent(child); /* assert( XfeIsManager(w) ); */ if (request->request_mode & XtCWQueryOnly) { return XtGeometryYes; } if (request->request_mode & CWX) { _XfeX(child) = request->x; } if (request->request_mode & CWY) { _XfeY(child) = request->y; } if (request->request_mode & CWWidth) { _XfeWidth(child) = request->width; } if (request->request_mode & CWHeight) { _XfeHeight(child) = request->height; } if (request->request_mode & CWBorderWidth) { _XfeBorderWidth(child) = request->border_width; } /* * This should be a lot more clever. We dont want to always * re layout the children. It works for now, but it could be * a lot more efficient. -re */ if (XfeIsManager(w)) { /* Layout the widget */ _XfeManagerLayoutWidget(w); } else { XfeResize(w); } return XtGeometryYes; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* */ /* XfeMoveChildrenByOffset Move all children of a manager by an */ /* (x,y) offset. */ /* */ /*----------------------------------------------------------------------*/ /* extern */ void XfeMoveChildrenByOffset(Widget w,int x_offset,int y_offset) { Cardinal i; assert( XmIsManager(w) ); /* Make sure the widget is alive */ if (!_XfeIsAlive(w)) { return; } /* Makre sure the offset is something */ if ((x_offset == 0) && (y_offset == 0)) { return; } i = _XfemNumChildren(w); /* for (i = _XfemNumChildren(w) - 1; i >= 0; i--) */ while (i--) { Widget child = _XfeChildrenIndex(w,i); if (_XfeIsAlive(child)) { _XfeMoveWidget(child, _XfeX(child) + x_offset, _XfeY(child) + y_offset); } } } /*----------------------------------------------------------------------*/