home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume10
/
xt-examples
/
part05
/
MinMax.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-04
|
16KB
|
513 lines
/***********************************************************
Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute these examples for any
purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation,
and that the name of Digital not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include <X11/IntrinsicP.h> /* Intrinsics header file */
#include <X11/StringDefs.h> /* Resource string definitions */
#include "MinMaxP.h" /* MinMax private header file */
#include "LabelGadge.h" /* To check LabelGadgets */
#define Offset(field) XtOffsetOf(MinMaxRec, minMax.field)
static XtResource resources[] = {
{XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
Offset(margin), XtRImmediate, (XtPointer) 10},
};
#undef Offset
#define Offset(field) XtOffsetOf(MinMaxConstraintRec, field)
static XtResource constraintResources[] = {
{XtNminWidth, XtCMinWidth, XtRShort, sizeof(short),
Offset(minMax.min_width), XtRImmediate, (XtPointer) -1},
{XtNmaxWidth, XtCMaxWidth, XtRShort, sizeof(short),
Offset(minMax.max_width), XtRImmediate, (XtPointer) -1},
{XtNminHeight, XtCMinHeight, XtRShort, sizeof(short),
Offset(minMax.min_height), XtRImmediate, (XtPointer) -1},
{XtNmaxHeight, XtCMaxHeight, XtRShort, sizeof(short),
Offset(minMax.max_height), XtRImmediate, (XtPointer) -1},
};
#undef Offset
/* Forward declarations */
static void ChangeManaged(), Initialize(), ConstraintInitialize(),
Resize(), InsertChild(), DeleteChild(), Redisplay();
static XtGeometryResult GeometryManager();
static Boolean SetValues(), AcceptFocus(), ConstraintSetValues();
static CompositeClassExtensionRec compositeExtension = {
/* next_extension */ NULL,
/* record_type */ NULLQUARK,
/* version */ XtCompositeExtensionVersion,
/* record_size */ sizeof(CompositeClassExtensionRec),
/* accepts_objects */ TRUE
};
MinMaxClassRec minMaxClassRec = {
/* Core class part */
{
/* superclass */ (WidgetClass) &constraintClassRec,
/* class_name */ "MinMax",
/* widget_size */ sizeof(MinMaxRec),
/* class_initialize */ NULL,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ XtExposeCompressMultiple,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ NULL,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ AcceptFocus,
/* version */ XtVersion,
/* callback offsets */ NULL,
/* tm_table */ NULL,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ NULL,
/* extension */ NULL,
},
/* Composite class part */
{
/* geometry_manager */ GeometryManager,
/* change_managed */ ChangeManaged,
/* insert_child */ InsertChild,
/* delete_child */ DeleteChild,
/* extension */ (XtPointer) &compositeExtension,
},
/* Constraint class part */
{
/* resources */ constraintResources,
/* num_resources */ XtNumber(constraintResources),
/* constraint_size */ sizeof(MinMaxConstraintRec),
/* initialize */ ConstraintInitialize,
/* destroy */ NULL,
/* set_values */ ConstraintSetValues,
/* extension */ NULL
},
/* MinMax class part */
{
/* extension */ NULL,
}
};
WidgetClass minMaxWidgetClass = (WidgetClass) &minMaxClassRec;
static void InsertChild(w)
Widget w;
{
String params[2];
Cardinal num_params;
Widget parent = XtParent(w);
if (!XtIsWidget(w) && !XtIsSubclass(w, labelGadgetClass)) {
params[0] = XtClass(w)->core_class.class_name;
params[1] = XtClass(parent)->core_class.class_name;
num_params = 2;
XtAppErrorMsg(XtWidgetToApplicationContext(w),
"childError", "class", "WidgetError",
"Children of class %s cannot be added to %n widgets",
params, &num_params);
}
(*((CompositeWidgetClass)(minMaxWidgetClass->
core_class.superclass))->composite_class.insert_child) (w);
}
static void DeleteChild(w)
Widget w;
{
MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
if (minMax->minMax.last_focus == w) {
minMax->minMax.last_focus = NULL;
}
(*((CompositeWidgetClass)(minMaxWidgetClass->
core_class.superclass))->composite_class.delete_child) (w);
}
static void Initialize(req, new, args, num_args)
Widget req, new;
ArgList args;
Cardinal *num_args;
{
((MinMaxWidget) new)->minMax.last_focus = NULL;
}
static void CheckConstraint(w, smaller, larger, which)
Widget w;
short *smaller, *larger;
String which;
{
String params[3];
Cardinal num_params;
if (*smaller > *larger) {
params[0] = params[1] = which;
params[2] = XtName(w);
num_params = 3;
XtAppWarningMsg(XtWidgetToApplicationContext(w),
"constraintError",
"width", "WidgetError",
"Min %s greater than max %s for widget %s",
params, &num_params);
*smaller = *larger;
}
}
static void ResizeWithinConstraints(w, width, height)
Widget w;
Dimension *width, *height;
{
register MinMaxConstraint mmc =
(MinMaxConstraint) w->core.constraints;
if (*width < mmc->minMax.min_width) {
*width = mmc->minMax.min_width;
} else if (*width > mmc->minMax.max_width) {
*width = mmc->minMax.max_width;
}
if (*height < mmc->minMax.min_height) {
*height = mmc->minMax.min_height;
} else if (*height > mmc->minMax.max_height) {
*height = mmc->minMax.max_height;
}
}
static void ConstraintInitialize(req, new, args, num_args)
Widget req, new;
ArgList args;
Cardinal *num_args;
{
MinMaxConstraint mmc = (MinMaxConstraint) new->core.constraints;
Dimension width = new->core.width, height = new->core.height;
#define MAXDIM 32768
if (mmc->minMax.min_width == -1 && mmc->minMax.max_width == -1) {
mmc->minMax.min_width = mmc->minMax.max_width = width;
}
if (mmc->minMax.min_height == -1 && mmc->minMax.max_height == -1) {
mmc->minMax.min_height = mmc->minMax.max_height = height;
}
if (mmc->minMax.min_width == -1) mmc->minMax.min_width = 1;
if (mmc->minMax.max_width == -1) mmc->minMax.max_width = MAXDIM;
if (mmc->minMax.min_height == -1) mmc->minMax.min_height = 1;
if (mmc->minMax.max_height == -1) mmc->minMax.max_height = MAXDIM;
CheckConstraint(new, &mmc->minMax.min_width,
&mmc->minMax.max_width, "width");
CheckConstraint(new, &mmc->minMax.min_height,
&mmc->minMax.max_height, "height");
ResizeWithinConstraints(new, &width, &height);
if (width != new->core.width || height != new->core.height) {
XtResizeWidget(new, width, height);
}
#undef MAXDIM
}
static void CalculateNewSize(minMax, width, height)
MinMaxWidget minMax;
register Dimension *width, *height;
{
register Widget child;
register int i;
int right, bottom;
*width = *height = 0;
for (i = 0; i < minMax->composite.num_children; i++) {
child = minMax->composite.children[i];
if (!XtIsManaged(child)) continue;
right = child->core.x + child->core.width +
2 * child->core.border_width;
bottom = child->core.y + child->core.height +
2 * child->core.border_width;
if (right > (int) *width) *width = right;
if (bottom > (int) *height) *height = bottom;
}
*width += minMax->minMax.margin;
*height += minMax->minMax.margin;
if (*width == 0) *width = 1;
if (*height == 0) *height = 1;
}
static void ResizeChildren(minMax, initiator)
MinMaxWidget minMax;
Widget initiator;
{
register Widget child;
register MinMaxConstraint mmc;
register int i;
int right, bottom;
int new_width, new_height;
int minMax_right = minMax->core.width - minMax->minMax.margin,
minMax_bottom = minMax->core.height - minMax->minMax.margin;
for (i = 0; i < minMax->composite.num_children; i++) {
child = minMax->composite.children[i];
if (!XtIsManaged(child) || child == initiator) continue;
mmc = (MinMaxConstraint) child->core.constraints;
new_width = child->core.width;
new_height = child->core.height;
right = child->core.x + child->core.width +
2 * child->core.border_width;
bottom = child->core.y + child->core.height +
2 * child->core.border_width;
if (right > minMax_right &&
child->core.width > mmc->minMax.min_width) {
new_width -= right - minMax_right;
if (new_width < mmc->minMax.min_width) {
new_width = mmc->minMax.min_width;
}
} else if (right < minMax_right &&
child->core.width < mmc->minMax.max_width) {
new_width += minMax_right - right;
if (new_width > mmc->minMax.max_width) {
new_width = mmc->minMax.max_width;
}
}
if (bottom > minMax_bottom &&
child->core.height > mmc->minMax.min_height) {
new_height -= bottom - minMax_bottom;
if (new_height < mmc->minMax.min_height) {
new_height = mmc->minMax.min_height;
}
} else if (bottom < minMax_bottom &&
child->core.height < mmc->minMax.max_height) {
new_height += minMax_bottom - bottom;
if (new_height > mmc->minMax.max_height) {
new_height = mmc->minMax.max_height;
}
}
XtResizeWidget(child, new_width, new_height,
child->core.border_width);
}
}
static void Resize(w)
Widget w;
{
ResizeChildren((MinMaxWidget) w, (Widget) NULL);
}
static void ChangeManaged(w)
Widget w;
{
MinMaxWidget minMax = (MinMaxWidget) w;
XtWidgetGeometry request;
XtGeometryResult result;
CalculateNewSize(minMax, &request.width, &request.height);
if (request.width != minMax->core.width ||
request.height != minMax->core.height) {
request.request_mode = CWWidth | CWHeight;
do {
result = XtMakeGeometryRequest(w,
&request, (XtWidgetGeometry *) NULL);
} while (result == XtGeometryAlmost);
if (result == XtGeometryYes) {
ResizeChildren(minMax, (Widget) NULL);
}
}
}
static XtGeometryResult GeometryManager(w, desired, allowed)
Widget w;
XtWidgetGeometry *desired, *allowed;
{
MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
MinMaxConstraint mmc = (MinMaxConstraint) w->core.constraints;
XtWidgetGeometry request;
XtGeometryResult result;
Dimension save_width, save_height, save_border_width;
Position save_x, save_y;
#define Wants(flag) (desired->request_mode & flag)
#define RestoreGeometry(w) { \
w->core.x = save_x; w->core.y = save_y; \
w->core.width = save_width; w->core.height = save_height; \
w->core.border_width = save_border_width; }
/* If the desired change goes outside the constraints, say no */
if ((Wants(CWWidth) && (desired->width < mmc->minMax.min_width ||
desired->width > mmc->minMax.max_width)) ||
(Wants(CWHeight) &&
(desired->height < mmc->minMax.min_height ||
desired->height > mmc->minMax.max_height))) {
return XtGeometryNo;
}
/* Figure out how big we would be with this change */
save_x = w->core.x;
save_y = w->core.y;
save_width = w->core.width;
save_height = w->core.height;
save_border_width = w->core.border_width;
if (Wants(CWX)) w->core.x = desired->x;
if (Wants(CWY)) w->core.y = desired->y;
if (Wants(CWWidth)) w->core.width = desired->width;
if (Wants(CWHeight)) w->core.height = desired->height;
if (Wants(CWBorderWidth)) {
w->core.border_width = desired->border_width;
}
CalculateNewSize(minMax, &request.width, &request.height);
if (request.width == minMax->core.width &&
request.height == minMax->core.height) {
if (Wants(XtCWQueryOnly)) RestoreGeometry(w);
return XtGeometryYes;
}
/* We need to change size in order to accommodate; see if we can */
request.request_mode = CWWidth | CWHeight;
if (Wants(XtCWQueryOnly)) request.request_mode |= XtCWQueryOnly;
result = XtMakeGeometryRequest((Widget) minMax, &request, NULL);
if (result == XtGeometryAlmost) result = XtGeometryNo;
if (result == XtGeometryYes && !Wants(XtCWQueryOnly)) {
ResizeChildren(minMax, w);
return XtGeometryYes;
}
/* Undo the saved changes */
RestoreGeometry(w);
return result;
#undef Wants
#undef RestoreGeometry
}
static Boolean SetValues(old, req, new, args, num_args)
Widget old, req, new;
ArgList args;
Cardinal *num_args;
{
register MinMaxWidget oldminMax = (MinMaxWidget) old;
register MinMaxWidget newminMax = (MinMaxWidget) new;
if (newminMax->minMax.margin != oldminMax->minMax.margin ||
newminMax->core.width == 0 ||
newminMax->core.height == 0) {
CalculateNewSize(newminMax,
&newminMax->core.width, &newminMax->core.height);
}
return FALSE;
}
static Boolean ConstraintSetValues(old, req, new, args, num_args)
Widget old, req;
ArgList args;
Cardinal *num_args;
register Widget new;
{
register MinMaxConstraint mmc =
(MinMaxConstraint) new->core.constraints;
CheckConstraint(new, &mmc->minMax.min_width,
&mmc->minMax.max_width, "width");
CheckConstraint(new, &mmc->minMax.min_height,
&mmc->minMax.max_height, "height");
ResizeWithinConstraints(new, &new->core.width, &new->core.height);
return FALSE;
}
static Boolean AcceptFocus(w, time)
Widget w;
Time *time;
{
MinMaxWidget minMax = (MinMaxWidget) w;
register int i;
if (minMax->minMax.last_focus != NULL &&
XtIsManaged(minMax->minMax.last_focus)) {
if (XtCallAcceptFocus(minMax->minMax.last_focus, time)) {
return TRUE;
}
}
for (i = 0; i < minMax->composite.num_children; i++) {
if (!XtIsManaged(minMax->composite.children[i])) continue;
if (XtCallAcceptFocus(minMax->composite.children[i], time)) {
minMax->minMax.last_focus = minMax->composite.children[i];
return TRUE;
}
}
minMax->minMax.last_focus = NULL;
return FALSE;
}
static void Redisplay(w, event, region)
Widget w;
XEvent *event;
Region region;
{
CompositeWidget comp = (CompositeWidget) w;
int i;
Widget c; /* child */
for (i = 0; i < comp->composite.num_children; i++) {
c = comp->composite.children[i];
if (XtIsManaged(c) && XtIsSubclass(c, labelGadgetClass) &&
XRectInRegion(region, c->core.x, c->core.y,
c->core.width + 2*c->core.border_width,
c->core.height + 2*c->core.border_width)
!= RectangleOut) {
(*(XtClass(c)->core_class.expose))(c, event, region);
}
}
}