/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* HISTORY
*/
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$XConsortium: Frame.c /main/18 1996/10/15 15:01:45 cde-osf $"
#endif
#endif
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Xm/DrawP.h>
#include <Xm/FrameP.h>
#include <Xm/GadgetP.h>
#include <Xm/VaSimpleP.h>
#include "GMUtilsI.h"
#include "RepTypeI.h"
#include "XmI.h"
#define GetFrameConstraint(w) \
(&((XmFrameConstraintPtr) (w)->core.constraints)->frame)
/******** Static Function Declarations ********/
static void CheckSetChildType(Widget wid,
int offset,
XrmValue *value);
static void DrawShadow(
XmFrameWidget fw) ;
static void ClearShadow(
XmFrameWidget fw) ;
static void ConfigureChildren(
XmFrameWidget fw,
Widget instigator,
XtWidgetGeometry *inst_desired) ;
static void ClassPartInitialize(
WidgetClass wc) ;
static void Initialize(
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static void Resize(
Widget wid) ;
static void Redisplay(
Widget wid,
XEvent *event,
Region region) ;
static XtGeometryResult GeometryManager(
Widget w,
XtWidgetGeometry *request,
XtWidgetGeometry *reply) ;
static void ChangeManaged(
Widget wid) ;
static Boolean SetValues(
Widget cw,
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static XtGeometryResult QueryGeometry(
Widget wid,
XtWidgetGeometry *request,
XtWidgetGeometry *ret) ;
static void CalcFrameSize(
XmFrameWidget fw,
#if NeedWidePrototypes
int titleWidth,
int titleHeight,
int titleBorder,
int workWidth,
int workHeight,
int workBorder,
#else
Dimension titleWidth,
Dimension titleHeight,
Dimension titleBorder,
Dimension workWidth,
Dimension workHeight,
Dimension workBorder,
#endif /* NeedWidePrototypes */
Dimension *fwWidth,
Dimension *fwHeight) ;
static void CalcWorkAreaSize(
XmFrameWidget fw,
Dimension *workWidth,
Dimension *workHeight,
#if NeedWidePrototypes
int workBorder,
int fwWidth,
int fwHeight) ;
#else
Dimension workBorder,
Dimension fwWidth,
Dimension fwHeight) ;
#endif /* NeedWidePrototypes */
static void CalcTitleExtent(
XmFrameWidget fw,
#if NeedWidePrototypes
int titleHeight,
int titleBorder,
#else
Dimension titleHeight,
Dimension titleBorder,
#endif /* NeedWidePrototypes */
Dimension *titleExtent,
Position *titleY,
Dimension *shadowWidth,
Position *shadowY) ;
static void ConstraintInitialize(
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static Boolean ConstraintSetValues(
Widget cw,
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static void ConstraintDestroy(
Widget w) ;
/******** End Static Function Declarations ********/
static XmSyntheticResource syn_resources[] =
{
{ XmNmarginWidth,
sizeof (Dimension),
XtOffsetOf( struct _XmFrameRec, frame.margin_width),
XmeFromHorizontalPixels,
XmeToHorizontalPixels },
{ XmNmarginHeight,
sizeof (Dimension),
XtOffsetOf( struct _XmFrameRec, frame.margin_height),
XmeFromVerticalPixels,
XmeToVerticalPixels, }
};
static XtResource resources[] =
{
{ XmNmarginWidth,
XmCMarginWidth,
XmRHorizontalDimension,
sizeof (Dimension),
XtOffsetOf( struct _XmFrameRec, frame.margin_width),
XmRImmediate, (XtPointer) 0 },
{ XmNmarginHeight,
XmCMarginHeight,
XmRVerticalDimension,
sizeof (Dimension),
XtOffsetOf( struct _XmFrameRec, frame.margin_height),
XmRImmediate, (XtPointer) 0 },
{ XmNshadowType,
XmCShadowType,
XmRShadowType,
sizeof (unsigned char),
XtOffsetOf( struct _XmFrameRec, frame.shadow_type),
XmRImmediate, (XtPointer) XmINVALID_DIMENSION },
{ XmNshadowThickness,
XmCShadowThickness,
XmRHorizontalDimension,
sizeof (Dimension),
XtOffsetOf( struct _XmFrameRec, manager.shadow_thickness),
XmRImmediate, (XtPointer) XmINVALID_DIMENSION }
};
static XmSyntheticResource syn_constraints[] =
{
{ XmNchildHorizontalSpacing, sizeof (Dimension),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_h_spacing),
XmeFromHorizontalPixels, XmeToHorizontalPixels }
};
static XtResource constraints[] =
{
{ "pri.vate", "Pri.vate", XmRInt,
sizeof (int),
XtOffsetOf( struct _XmFrameConstraintRec, frame.unused),
XmRImmediate, (XtPointer) 0 },
{ XmNchildType, XmCChildType, XmRChildType,
sizeof (unsigned char),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_type),
XmRCallProc, (XtPointer) CheckSetChildType },
/* add a dup in 2.0 with new local names */
{ XmNframeChildType, XmCFrameChildType, XmRChildType,
sizeof (unsigned char),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_type),
XmRCallProc, (XtPointer) CheckSetChildType },
{ XmNchildHorizontalAlignment, XmCChildHorizontalAlignment,
XmRChildHorizontalAlignment,
sizeof (unsigned char),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_h_alignment),
XmRImmediate, (XtPointer) XmALIGNMENT_BEGINNING },
{ XmNchildVerticalAlignment, XmCChildVerticalAlignment,
XmRChildVerticalAlignment,
sizeof (unsigned char),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_v_alignment),
XmRImmediate, (XtPointer) XmALIGNMENT_CENTER },
{ XmNchildHorizontalSpacing, XmCChildHorizontalSpacing,
XmRHorizontalDimension, sizeof (Dimension),
XtOffsetOf( struct _XmFrameConstraintRec, frame.child_h_spacing),
XmRImmediate, (XtPointer) XmINVALID_DIMENSION}
};
/****************************************************************
*
* Full class record constant
*
****************************************************************/
externaldef(xmframeclassrec) XmFrameClassRec xmFrameClassRec =
{
{ /* core_class fields */
(WidgetClass) &xmManagerClassRec, /* superclass */
"XmFrame", /* class_name */
sizeof(XmFrameRec), /* widget_size */
NULL, /* class_initialize */
ClassPartInitialize, /* class_part_init */
FALSE, /* class_inited */
Initialize, /* initialize */
NULL, /* initialize_hook */
XtInheritRealize, /* realize */
NULL, /* actions */
0, /* num_actions */
resources, /* resources */
XtNumber(resources), /* num_resources */
NULLQUARK, /* xrm_class */
TRUE, /* compress_motion */
XtExposeCompressMaximal, /* compress_exposure */
TRUE, /* compress_enterlv */
FALSE, /* visible_interest */
NULL, /* destroy */
Resize, /* resize */
Redisplay, /* expose */
SetValues, /* set_values */
NULL, /* set_values_hook */
XtInheritSetValuesAlmost, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
XtInheritTranslations, /* tm_table */
QueryGeometry, /* query_geometry */
NULL, /* display_accelerator */
NULL, /* extension */
},
{ /* composite_class fields */
GeometryManager, /* geometry_manager */
ChangeManaged, /* change_managed */
XtInheritInsertChild, /* insert_child */
XtInheritDeleteChild, /* delete_child */
NULL, /* extension */
},
{ /* constraint_class fields */
constraints, /* resource list */
XtNumber(constraints), /* num resources */
sizeof (XmFrameConstraintRec), /* constraint size */
ConstraintInitialize, /* init proc */
ConstraintDestroy, /* destroy proc */
ConstraintSetValues, /* set values proc */
NULL, /* extension */
},
{ /* manager class */
XtInheritTranslations, /* translations */
syn_resources, /* syn resources */
XtNumber(syn_resources), /* num syn_resources */
syn_constraints, /* get_cont_resources */
XtNumber(syn_constraints), /* num_get_cont_resources */
XmInheritParentProcess, /* parent_process */
NULL, /* extension */
},
{ /* frame class */
NULL, /* extension */
}
};
externaldef(xmframewidgetclass) WidgetClass xmFrameWidgetClass =
(WidgetClass) &xmFrameClassRec;
/************************************************************************
*
* CheckSetChildType
* default proc for the new childType resource.
* if this is called and child_type is INVALID, childType was
* not set, so default it, otherwise child_type was set and this
* one is not, so don't change it.
*
************************************************************************/
/*ARGSUSED*/
static void
CheckSetChildType(Widget wid,
int offset,
XrmValue *value)
{
XmFrameConstraint fc = GetFrameConstraint(wid);
static unsigned char child_type = XmFRAME_WORKAREA_CHILD ;
if (fc->unused) /* Been here already, so default it .. */
value->addr = (XPointer) &child_type;
else {
value->addr = (XPointer) &(fc->child_type);
fc->unused = 1;
}
}
/************************************************************************
*
* DrawShadow
* Draw the Frame shadow
*
************************************************************************/
static void
DrawShadow(
XmFrameWidget fw )
{
if (XtIsRealized((Widget)fw)) {
XmeDrawShadows(XtDisplay (fw), XtWindow (fw),
fw->manager.top_shadow_GC, fw->manager.bottom_shadow_GC,
fw->frame.old_shadow_x, fw->frame.old_shadow_y,
fw->frame.old_width, fw->frame.old_height,
fw->frame.old_shadow_thickness, fw->frame.shadow_type);
}
}
/************************************************************************
*
* ClearShadow
* Erase the Frame shadow
*
************************************************************************/
static void
ClearShadow(
XmFrameWidget fw )
{
if (XtIsRealized((Widget)fw)) {
XmeClearBorder (XtDisplay(fw), XtWindow(fw),
fw->frame.old_shadow_x,
fw->frame.old_shadow_y,
fw->frame.old_width,
fw->frame.old_height,
fw->frame.old_shadow_thickness);
}
}
/************************************************************************
*
* ConfigureChildren
* Configure the title and work area if they aren't instigaror
* of the request (Yes policy). Compute the shadow location.
*
************************************************************************/
static void
ConfigureChildren(
XmFrameWidget fw,
Widget instigator,
XtWidgetGeometry * inst_geometry)
{
Widget child;
XmFrameConstraint fc;
Position childX = 0;
Position childY;
Dimension childWidth;
Dimension childHeight;
Dimension childBW;
Dimension shadowThickness = fw->manager.shadow_thickness;
Dimension titleExtent = shadowThickness;
Dimension shadowHeight = fw->core.height;
Position shadowY = 0;
XtWidgetGeometry title_reply;
Dimension spacing;
if (fw->frame.title_area && XtIsManaged(fw->frame.title_area)) {
child = fw->frame.title_area;
fc = GetFrameConstraint(child);
spacing = shadowThickness + fc->child_h_spacing;
/* asking the preferred geometry without constraint */
XtQueryGeometry (child, NULL, &title_reply);
childWidth = (title_reply.request_mode & CWWidth) ?
title_reply.width : child->core.width;
childHeight = (title_reply.request_mode & CWHeight) ?
title_reply.height : child->core.height;
childBW = child->core.border_width;
if (child == instigator) {
childWidth = (inst_geometry->request_mode & CWWidth) ?
inst_geometry->width : childWidth;
childHeight = (inst_geometry->request_mode & CWHeight) ?
inst_geometry->height : childHeight;
childBW = (inst_geometry->request_mode & CWBorderWidth) ?
inst_geometry->border_width : childBW;
}
if (childWidth + 2 * (spacing + childBW) > fw->core.width) {
if (fw->core.width > 2 * (spacing + childBW))
childWidth = fw->core.width - 2 * (spacing + childBW);
else
childWidth = 1;
}
switch (fc->child_h_alignment) {
case(XmALIGNMENT_BEGINNING):
if (LayoutIsRtoLM(fw))
childX = fw->core.width - spacing -
childWidth - 2 * childBW;
else
childX = spacing;
break;
case(XmALIGNMENT_CENTER):
childX = fw->core.width/2 - childWidth/2 - childBW;
break;
case(XmALIGNMENT_END):
default:
if (LayoutIsRtoLM(fw))
childX = spacing;
else
childX = fw->core.width - spacing -
childWidth - 2 * childBW;
break;
}
CalcTitleExtent (fw, childHeight, childBW,
&titleExtent, &childY, &shadowHeight, &shadowY);
if (child != instigator) {
XmeConfigureObject (child, childX, childY, childWidth,
childHeight, childBW);
}
else {
/* Do not resize the instigator, just return GeometryYes */
inst_geometry->request_mode = CWX | CWY | CWWidth | CWHeight |
CWBorderWidth;
child->core.x = childX;
child->core.y = childY;
child->core.width = childWidth;
child->core.height = childHeight;
child->core.border_width = childBW;
}
}
if (fw->frame.work_area && XtIsManaged(fw->frame.work_area)) {
child = fw -> frame.work_area;
if (child != instigator)
childBW = child->core.border_width;
else
childBW = (inst_geometry->request_mode & CWBorderWidth) ?
inst_geometry->border_width : child->core.border_width;
CalcWorkAreaSize (fw, &childWidth, &childHeight, childBW,
fw->core.width, fw->core.height);
childX = shadowThickness + fw->frame.margin_width;
childY = titleExtent + fw->frame.margin_height;
if (child != instigator) {
XmeConfigureObject (child, childX, childY, childWidth, childHeight,
childBW);
}
else {
/* Do not resize the instigator, just return GeometryYes */
inst_geometry->request_mode = CWX | CWY | CWWidth | CWHeight |
CWBorderWidth;
child->core.x = childX;
child->core.y = childY;
child->core.width = childWidth;
child->core.height = childHeight;
child->core.border_width = childBW;
}
}
fw->frame.old_shadow_x = 0;
fw->frame.old_shadow_y = shadowY;
fw->frame.old_width = fw->core.width;
fw->frame.old_height = shadowHeight;
fw->frame.old_shadow_thickness = shadowThickness;
}
/************************************************************************
*
* ClassPartInitialize
* Set up the fast subclassing for the widget
*
************************************************************************/
static void
ClassPartInitialize(
WidgetClass wc )
{
_XmFastSubclassInit (wc, XmFRAME_BIT);
}
/************************************************************************
*
* Initialize
* Ensure that the width and height are not 0.
*
*************************************<->***********************************/
/*ARGSUSED*/
static void
Initialize(
Widget rw,
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmFrameWidget request = (XmFrameWidget) rw ;
XmFrameWidget new_w = (XmFrameWidget) nw;
new_w->frame.title_area = NULL;
new_w->frame.work_area = NULL;
new_w->frame.processing_constraints = False;
if (new_w->frame.shadow_type == (unsigned char) XmINVALID_DIMENSION)
{
if (XtIsShell (XtParent(new_w)))
{
new_w->frame.shadow_type = XmSHADOW_OUT;
}
else
{
new_w->frame.shadow_type = XmSHADOW_ETCHED_IN;
}
}
if (!XmRepTypeValidValue( XmRID_SHADOW_TYPE, new_w->frame.shadow_type,
(Widget) new_w))
{
new_w->frame.shadow_type = XmSHADOW_ETCHED_IN;
}
if (request->manager.shadow_thickness == XmINVALID_DIMENSION)
{
if (XtIsShell (XtParent(new_w)))
{
new_w->manager.shadow_thickness = 1;
}
else
{
new_w->manager.shadow_thickness = 2;
}
}
new_w->frame.old_shadow_x = 0;
new_w->frame.old_shadow_y = 0;
new_w->frame.old_width = new_w->core.width;
new_w->frame.old_height = new_w->core.height;
new_w->frame.old_shadow_thickness = new_w->manager.shadow_thickness;
}
/************************************************************************
*
* Resize
* Calculate the size of the children and resize.
*
************************************************************************/
static void
Resize(
Widget wid )
{
XmFrameWidget fw = (XmFrameWidget) wid ;
ClearShadow(fw);
ConfigureChildren(fw, NULL, NULL);
DrawShadow(fw);
}
/************************************************************************
*
* Redisplay
* General redisplay function called on exposure events.
*
************************************************************************/
static void
Redisplay(
Widget wid,
XEvent *event,
Region region )
{
XmFrameWidget fw = (XmFrameWidget) wid;
Widget title_area = fw->frame.title_area;
DrawShadow(fw);
/* since the shadow may have screw up the gadget title, while this
one won't get refresh, we have to redraw it manually */
if (title_area && XmIsGadget(title_area) && XtIsManaged(title_area))
{
XClearArea (XtDisplay(fw), XtWindow(fw),
title_area->core.x, title_area->core.y,
title_area->core.width, title_area->core.height,
False);
if (region && !XRectInRegion (region, title_area->core.x,
title_area->core.y, title_area->core.width, title_area->core.height))
{
XtExposeProc expose;
_XmProcessLock();
expose = title_area->core.widget_class->core_class.expose;
_XmProcessUnlock();
if (expose)
(*expose)(title_area, event, NULL);
}
}
XmeRedisplayGadgets( (Widget) fw, event, region);
}
/************************************************************************
*
* Geometry Manager
* Take the requested geometry, calculate the needed size for
* the frame and make a request to the frames parent.
* Requests to change x, y position are always denied.
*
************************************************************************/
static XtGeometryResult
GeometryManager(
Widget w,
XtWidgetGeometry *request,
XtWidgetGeometry *reply )
{
XmFrameWidget fw = (XmFrameWidget) XtParent(w);
Widget title_area = fw->frame.title_area;
Widget work_area = fw->frame.work_area;
Dimension req_width, req_height, req_bw;
Boolean query_only = False;
Boolean almost = False;
Dimension title_width = (title_area)?title_area->core.width:0;
Dimension title_height = (title_area)?title_area->core.height:0;
Dimension title_bw = (title_area)?title_area->core.border_width:0;
Dimension work_width = (work_area)?work_area->core.width:0;
Dimension work_height = (work_area)?work_area->core.height:0;
Dimension work_bw = (work_area)?work_area->core.border_width:0;
Dimension frame_width, frame_height;
XtWidgetGeometry parent_request;
XtWidgetGeometry parent_reply;
Dimension almost_width;
Dimension almost_height;
if (fw->frame.processing_constraints)
{
fw->frame.processing_constraints = False;
request -> border_width -= 1;
}
/* Set up the calculation variables according to the */
/* contents of the requested geometry. */
if (request -> request_mode & XtCWQueryOnly)
query_only = True;
if ((request -> request_mode & CWX) || (request -> request_mode & CWY))
almost = True;
if (request -> request_mode & CWWidth) req_width = request -> width;
else req_width = w -> core.width;
if (request -> request_mode & CWHeight) req_height = request -> height;
else req_height = w -> core.height;
if (request -> request_mode & CWBorderWidth)
req_bw = request -> border_width;
else req_bw = w -> core.border_width;
if (w == title_area)
{
title_width = req_width;
title_height = req_height;
title_bw = req_bw;
}
if (w == work_area)
{
work_width = req_width;
work_height = req_height;
work_bw = req_bw;
}
/* find the frame size based on the children preferred geometry */
CalcFrameSize (fw, title_width, title_height, title_bw,
work_width, work_height, work_bw,
&frame_width, &frame_height);
parent_request.request_mode = CWWidth | CWHeight;
if (almost || query_only) parent_request.request_mode |= XtCWQueryOnly;
parent_request.width = frame_width;
parent_request.height = frame_height;
switch (XtMakeGeometryRequest ((Widget)fw,
&parent_request, &parent_reply)) {
case XtGeometryYes:
if (!almost) {
if (!query_only) {
ClearShadow(fw);
ConfigureChildren(fw, w, request);
DrawShadow(fw);
}
return (XtGeometryYes);
} else {
almost_width = request->width;
almost_height = request->height;
}
break;
case XtGeometryNo:
if (w == title_area) {
/* we got a No, try to honor the title request anyway,
by resizing the work_area child */
if (!almost) {
if (!query_only) {
ClearShadow(fw);
ConfigureChildren(fw, w, request);
DrawShadow(fw);
}
return (XtGeometryYes);
} else {
almost_width = request->width;
almost_height = request->height;
}
} else return (XtGeometryNo);
break;
case XtGeometryAlmost:
if (w == title_area) {
/* we got an Almost, try to honor the title request anyway,
by accepting the deal and resizing the work_area child */
if (!almost) {
if (!query_only) {
ClearShadow(fw);
XtMakeResizeRequest((Widget)fw, parent_reply.width,
parent_reply.height, NULL, NULL);
ConfigureChildren(fw, w, request);
}
return (XtGeometryYes);
} else {
almost_width = request->width;
almost_height = request->height;
}
} else {
/* we got an Almost, accept the deal and
compute the work_area size */
CalcWorkAreaSize (fw, &almost_width, &almost_height,
req_bw, parent_reply.width,
parent_reply.height);
}
break;
default:
return (XtGeometryNo);
break;
}
/* Fallen through to an almost condition. Clear the x and y */
/* and set the width, height, and border. */
if (reply != NULL) {
reply -> request_mode = request -> request_mode & ~(CWX | CWY);
reply -> width = almost_width;
reply -> height = almost_height;
reply -> border_width = req_bw;
if (request -> request_mode & CWSibling)
reply -> sibling = request -> sibling;
if (request -> request_mode & CWStackMode)
reply -> stack_mode = request -> stack_mode;
return (XtGeometryAlmost);
}
return (XtGeometryNo);
}
/************************************************************************
*
* ChangeManaged
* Process a changed in managed state of the child. If its
* size is out of sync with the frame, make a resize request
* to change the size of the frame.
* Note: called before ConstraintDestroy.
*
************************************************************************/
static void
ChangeManaged(
Widget wid )
{
XmFrameWidget fw = (XmFrameWidget) wid ;
Widget title_area = (fw->frame.title_area &&
XtIsManaged(fw->frame.title_area)) ?
fw->frame.title_area : (Widget) NULL;
Dimension t_w = 0;
Dimension t_h = 0;
Dimension t_bw = (title_area) ? title_area->core.border_width : 0;
Widget work_area = (fw->frame.work_area &&
XtIsManaged(fw->frame.work_area)) ?
fw->frame.work_area : (Widget) NULL;
Dimension w_w = (work_area) ? work_area->core.width : 0;
Dimension w_h = (work_area) ? work_area->core.height : 0;
Dimension w_bw = (work_area) ? work_area->core.border_width : 0;
Dimension fwWidth, fwHeight;
if (title_area)
{
/* We don't want the current size of the title object -- width/height
** may have been set on it. Because we'll be forcing it to the size we
** want (see ConfigureChildren), we must use the "natural" size here,
** so query its value now. (Use current border_width.)
*/
XtWidgetGeometry title_reply;
XtQueryGeometry (title_area, NULL, &title_reply);
t_w = (title_reply.request_mode & CWWidth) ?
title_reply.width : title_area->core.width;
t_h = (title_reply.request_mode & CWHeight) ?
title_reply.height : title_area->core.height;
}
/* need to check on initial sizing (not null) */
if (XtIsRealized((Widget)fw) || (XtWidth(fw) == 0) || (XtHeight(fw) == 0)) {
CalcFrameSize (fw, t_w, t_h, t_bw, w_w, w_h, w_bw,
&fwWidth, &fwHeight);
while (XtMakeResizeRequest ((Widget) fw,
fwWidth, fwHeight,
&fwWidth, &fwHeight) == XtGeometryAlmost)
/*EMPTY*/;
ClearShadow(fw);
}
ConfigureChildren(fw, NULL, NULL);
DrawShadow(fw);
XmeNavigChangeManaged((Widget) fw);
}
/************************************************************************
*
* Set Values
* Adjust the size of the manager based on shadow thickness
* changes.
*
************************************************************************/
/*ARGSUSED*/
static Boolean
SetValues(
Widget cw,
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmFrameWidget current = (XmFrameWidget) cw ;
XmFrameWidget new_w = (XmFrameWidget) nw ;
Boolean redisplay = False;
Widget title_area = (new_w->frame.title_area &&
XtIsManaged(new_w->frame.title_area)) ?
new_w->frame.title_area : NULL;
Dimension t_w = (title_area) ? title_area->core.width : 0;
Dimension t_h = (title_area) ? title_area->core.height : 0;
Dimension t_bw = (title_area) ? title_area->core.border_width : 0;
Widget work_area = (new_w->frame.work_area &&
XtIsManaged(new_w->frame.work_area)) ?
new_w->frame.work_area : (Widget) NULL;
Dimension w_w = (work_area) ? work_area->core.width : 0;
Dimension w_h = (work_area) ? work_area->core.height : 0;
Dimension w_bw = (work_area) ? work_area->core.border_width : 0;
if (!XmRepTypeValidValue( XmRID_SHADOW_TYPE, new_w->frame.shadow_type,
(Widget) new_w))
{
new_w->frame.shadow_type = current->frame.shadow_type;
}
if (!XtIsRealized((Widget)new_w)) return False ;
if (new_w->frame.margin_width != current->frame.margin_width ||
new_w->frame.margin_height != current->frame.margin_height ||
new_w->manager.shadow_thickness != current->manager.shadow_thickness)
{
CalcFrameSize (new_w, t_w, t_h, t_bw, w_w, w_h, w_bw,
&new_w->core.width, &new_w->core.height);
}
if (new_w -> frame.shadow_type != current -> frame.shadow_type ||
new_w->frame.margin_width != current->frame.margin_width ||
new_w->frame.margin_height != current->frame.margin_height ||
new_w->manager.shadow_thickness != current->manager.shadow_thickness)
{
redisplay = True;
}
return (redisplay);
}
/************************************************************************
*
* QueryGeometry
* return width X height based on the children preferred sizes
*
************************************************************************/
static XtGeometryResult
QueryGeometry(
Widget widget,
XtWidgetGeometry *intended,
XtWidgetGeometry *desired )
{
Dimension work_width = 0, work_height = 0, work_bw = 0 ;
Dimension title_width = 0, title_height = 0, title_bw = 0 ;
XtWidgetGeometry child_pref ;
XmFrameWidget fw = (XmFrameWidget) widget ;
/* first determine what is the desired size, using the
preferred sizes of the title and the work_area, or the
current setting if no preference are given */
if (fw->frame.work_area) {
XtQueryGeometry (fw->frame.work_area, NULL, &child_pref);
if (IsWidth(&child_pref)) work_width = child_pref.width ;
else work_width = XtWidth(fw->frame.work_area);
if (IsHeight(&child_pref)) work_height = child_pref.height ;
else work_height = XtHeight(fw->frame.work_area);
if (IsBorder(&child_pref)) work_bw = child_pref.border_width ;
else work_bw = XtBorderWidth(fw->frame.work_area);
}
if (fw->frame.title_area) {
XtQueryGeometry (fw->frame.title_area, NULL, &child_pref);
if (IsWidth(&child_pref)) title_width = child_pref.width ;
else title_width = XtWidth(fw->frame.title_area);
if (IsHeight(&child_pref)) title_height = child_pref.height ;
else title_height = XtHeight(fw->frame.title_area);
if (IsBorder(&child_pref)) title_bw = child_pref.border_width ;
else title_bw = XtBorderWidth(fw->frame.title_area);
}
CalcFrameSize (fw,
title_width, title_height, title_bw,
work_width, work_height, work_bw,
&desired->width, &desired->height);
/* deal with user initial size setting */
if (!XtIsRealized(widget)) {
if (XtWidth(widget) != 0) desired->width = XtWidth(widget) ;
if (XtHeight(widget) != 0) desired->height = XtHeight(widget) ;
}
return XmeReplyToQueryGeometry(widget, intended, desired) ;
}
/************************************************************************
*
* CalcFrameSize
* Calculate the manager size based on the supplied width
* and height.
* Note: all of the dimensions passed in may be 0, in which case the return
* value is based on the frame's own visuals.
************************************************************************/
static void
CalcFrameSize(
XmFrameWidget fw,
#if NeedWidePrototypes
int titleWidth,
int titleHeight,
int titleBorder,
int workWidth,
int workHeight,
int workBorder,
#else
Dimension titleWidth,
Dimension titleHeight,
Dimension titleBorder,
Dimension workWidth,
Dimension workHeight,
Dimension workBorder,
#endif /* NeedWidePrototypes */
Dimension *fwWidth,
Dimension *fwHeight )
{
Dimension shadowThickness = fw->manager.shadow_thickness;
Dimension titleExtent = shadowThickness;
Dimension workMax = 0;
Dimension titleMax = 0;
if (fw->frame.title_area && XtIsManaged(fw->frame.title_area)) {
XmFrameConstraint fc = GetFrameConstraint(fw->frame.title_area);
CalcTitleExtent (fw, titleHeight, titleBorder, &titleExtent, NULL,
NULL, NULL);
titleMax = 2 * (shadowThickness + titleBorder + fc->child_h_spacing) +
titleWidth;
}
workMax = 2 * (workBorder + shadowThickness + fw->frame.margin_width) +
workWidth;
*fwWidth = MAX (workMax, titleMax);
if (*fwWidth == 0) *fwWidth = 1;
*fwHeight = workHeight + 2 * (workBorder + fw->frame.margin_height) +
shadowThickness + titleExtent;
if (*fwHeight == 0) *fwHeight = 1;
}
/************************************************************************
*
* CalcWorkAreaSize
* Calculate the work area size based on the supplied width
* and height.
*
************************************************************************/
static void
CalcWorkAreaSize(
XmFrameWidget fw,
Dimension *workWidth,
Dimension *workHeight,
#if NeedWidePrototypes
int workBorder,
int fwWidth,
int fwHeight )
#else
Dimension workBorder,
Dimension fwWidth,
Dimension fwHeight )
#endif /* NeedWidePrototypes */
{
Widget title = fw->frame.title_area;
Dimension shadowThickness = fw->manager.shadow_thickness;
Dimension titleExtent = shadowThickness;
int temp;
if (title && XtIsManaged(title))
CalcTitleExtent (fw, title->core.height, title->core.border_width,
&titleExtent, NULL, NULL, NULL);
temp = (int) fwWidth -
(int) (2 * (workBorder + shadowThickness + fw->frame.margin_width));
if (temp <= 0) *workWidth = 1;
else *workWidth = (Dimension) temp;
temp = (int) fwHeight -
(int) (2 * (workBorder + fw->frame.margin_height) +
shadowThickness + titleExtent);
if (temp <= 0) *workHeight = 1;
else *workHeight = (Dimension) temp;
}
/************************************************************************
*
* CalcTitleExtent
* Calculate layout parameters which depend on the title.
*
* titleExtent: vertical space above the work area.
* titleY: y position of the title.
* shadowHeight: vertical size of the shadow rectangle.
* shadowY: y position of the shadow rectangle.
*
************************************************************************/
static void
CalcTitleExtent(
XmFrameWidget fw,
#if NeedWidePrototypes
int titleHeight,
int titleBorder,
#else
Dimension titleHeight,
Dimension titleBorder,
#endif /* NeedWidePrototypes */
Dimension *titleExtent,
Position *titleY,
Dimension *shadowHeight,
Position *shadowY)
{
XmFrameConstraint fc = GetFrameConstraint(fw->frame.title_area);
Dimension shadowThickness = fw->manager.shadow_thickness;
Dimension extent;
Position ty;
Dimension sh;
Position sy;
Dimension base;
Dimension *lines;
int nlines;
Dimension total = titleHeight + 2 * titleBorder;
switch (fc->child_v_alignment) {
case(XmALIGNMENT_BASELINE_TOP):
case(XmALIGNMENT_BASELINE_BOTTOM):
if (XmWidgetGetBaselines (fw->frame.title_area, &lines, &nlines)) {
if (fc->child_v_alignment == XmALIGNMENT_BASELINE_TOP)
base = lines[0];
else
base = lines[nlines - 1];
XtFree((char *)lines);
}
else {
base = total/2;
}
ty = (base + titleBorder > shadowThickness/2) ?
0 : shadowThickness/2 - (base + titleBorder);
extent = ty + MAX(total, titleBorder + base + shadowThickness/2);
sy = (base + titleBorder > shadowThickness/2) ?
base + titleBorder - shadowThickness/2 : 0;
sh = ((Dimension) sy >= fw->core.height) ?
1 : fw->core.height - sy;
break;
case(XmALIGNMENT_CENTER):
ty = (total > shadowThickness) ? 0 : (shadowThickness - total)/2;
extent = MAX(shadowThickness, total);
sy = (shadowThickness > total) ? 0 : total/2 - shadowThickness/2;
sh = ((Dimension) sy >= fw->core.height) ?
1 : fw->core.height - sy;
break;
case(XmALIGNMENT_WIDGET_TOP):
ty = 0;
extent = shadowThickness + total;
sy = total;
sh = ((Dimension) sy >= fw->core.height) ?
1 : fw->core.height - sy;
break;
case(XmALIGNMENT_WIDGET_BOTTOM):
default:
ty = shadowThickness;
extent = shadowThickness + total;
sy = 0;
sh = fw->core.height;
break;
}
if (titleExtent) *titleExtent = extent;
if (titleY) *titleY = ty;
if (shadowHeight) *shadowHeight = sh;
if (shadowY) *shadowY = sy;
}
/************************************************************************
*
* Constraint Initialize
*
*************************************<->***********************************/
/*ARGSUSED*/
static void
ConstraintInitialize(
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmFrameConstraint nc;
XmFrameConstraint bc;
XmFrameWidget fw;
if (!XtIsRectObj (nw)) return;
nc = GetFrameConstraint(nw);
fw = (XmFrameWidget)XtParent(nw);
if (!XmRepTypeValidValue( XmRID_CHILD_TYPE, nc->child_type, nw))
{
nc->child_type = XmFRAME_GENERIC_CHILD;
}
else
{
switch (nc->child_type)
{
case (XmFRAME_TITLE_CHILD) :
if (fw->frame.title_area != NULL) {
bc = GetFrameConstraint(fw->frame.title_area);
bc->child_type = XmFRAME_GENERIC_CHILD;
}
fw->frame.title_area = nw;
if (nc->child_h_spacing == (Dimension) XmINVALID_DIMENSION)
nc->child_h_spacing = MAX(10,fw->frame.margin_width);
break;
case (XmFRAME_WORKAREA_CHILD) :
if (fw->frame.work_area != NULL) {
bc = GetFrameConstraint(fw->frame.work_area);
bc->child_type = XmFRAME_GENERIC_CHILD;
}
fw->frame.work_area = nw;
break;
case (XmFRAME_GENERIC_CHILD) :
break;
}
}
if (!XmRepTypeValidValue( XmRID_CHILD_HORIZONTAL_ALIGNMENT,
nc->child_h_alignment, nw))
{
nc->child_h_alignment = XmALIGNMENT_BEGINNING;
}
if (!XmRepTypeValidValue( XmRID_CHILD_VERTICAL_ALIGNMENT,
nc->child_v_alignment, nw))
{
nc->child_v_alignment = XmALIGNMENT_CENTER;
}
}
/************************************************************************
*
* Constraint SetValues
*
************************************************************************/
/*ARGSUSED*/
static Boolean
ConstraintSetValues(
Widget cw,
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmFrameConstraint nc;
XmFrameConstraint cc;
XmFrameConstraint bc;
XmFrameWidget fw;
Boolean reconfigure = False;
if (!XtIsRectObj (nw)) return (False);
nc = GetFrameConstraint(nw);
cc = GetFrameConstraint(cw);
fw = (XmFrameWidget)XtParent(nw);
if (nc->child_type != cc->child_type)
{
if( !XmRepTypeValidValue( XmRID_CHILD_TYPE, nc->child_type, nw) )
{
nc->child_type = cc->child_type;
}
else
{
switch(nc->child_type)
{
case (XmFRAME_TITLE_CHILD) :
if (fw->frame.title_area != NULL) {
bc = GetFrameConstraint(fw->frame.title_area);
bc->child_type = XmFRAME_GENERIC_CHILD;
}
fw->frame.title_area = nw;
if (nc->child_h_spacing == (Dimension) XmINVALID_DIMENSION)
nc->child_h_spacing = MAX(10,fw->frame.margin_width);
break;
case (XmFRAME_WORKAREA_CHILD) :
if (fw->frame.work_area != NULL) {
bc = GetFrameConstraint(fw->frame.work_area);
bc->child_type = XmFRAME_GENERIC_CHILD;
}
fw->frame.work_area = nw;
break;
case (XmFRAME_GENERIC_CHILD) :
if (nw == fw->frame.title_area)
fw->frame.title_area = NULL;
else if (nw == fw->frame.work_area)
fw->frame.work_area = NULL;
break;
}
}
}
if (nc->child_h_alignment != cc->child_h_alignment &&
!XmRepTypeValidValue( XmRID_CHILD_HORIZONTAL_ALIGNMENT,
nc->child_h_alignment, nw))
{
nc->child_h_alignment = cc->child_h_alignment;
}
if (nc->child_v_alignment != cc->child_v_alignment &&
!XmRepTypeValidValue( XmRID_CHILD_VERTICAL_ALIGNMENT,
nc->child_v_alignment, nw))
{
nc->child_v_alignment = cc->child_v_alignment;
}
if (nc->child_type == XmFRAME_TITLE_CHILD &&
(nc->child_h_alignment != cc->child_h_alignment ||
nc->child_h_spacing != cc->child_h_spacing ||
nc->child_v_alignment != cc->child_v_alignment))
{
reconfigure = True;
}
if (nc->child_type != cc->child_type)
{
reconfigure = True;
}
if (reconfigure && XtIsManaged (nw) && XtIsRealized (nw))
{
fw->frame.processing_constraints = True;
nw->core.border_width+=1; /* force call to GM */
return (True);
}
return (False);
}
/************************************************************************
*
* Constraint Destroy
*
*************************************<->***********************************/
static void
ConstraintDestroy(
Widget w )
{
XmFrameWidget fw;
if (!XtIsRectObj (w)) return;
fw = (XmFrameWidget)XtParent(w);
if (w == fw->frame.title_area)
fw->frame.title_area = NULL;
else if (w == fw->frame.work_area)
fw->frame.work_area = NULL;
}
/************************************************************************
*
* XmCreateFrame
* Create an instance of a frame widget and return the widget id.
*
************************************************************************/
Widget
XmCreateFrame(
Widget parent,
char *name,
ArgList arglist,
Cardinal argcount )
{
return (XtCreateWidget (name, xmFrameWidgetClass,
parent, arglist, argcount));
}
Widget
XmVaCreateFrame(
Widget parent,
char *name,
...)
{
register Widget w;
va_list var;
int count;
Va_start(var,name);
count = XmeCountVaListSimple(var);
va_end(var);
Va_start(var, name);
w = XmeVLCreateWidget(name,
xmFrameWidgetClass,
parent, False,
var, count);
va_end(var);
return w;
}
Widget
XmVaCreateManagedFrame(
Widget parent,
char *name,
...)
{
Widget w = NULL;
va_list var;
int count;
Va_start(var, name);
count = XmeCountVaListSimple(var);
va_end(var);
Va_start(var, name);
w = XmeVLCreateWidget(name,
xmFrameWidgetClass,
parent, True,
var, count);
va_end(var);
return w;
}