00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <X11/IntrinsicP.h>
00058 #include <X11/StringDefs.h>
00059 #include <X11/Xmu/Misc.h>
00060 #include <X11/Xaw3d/XawInit.h>
00061 #include <X11/Xaw3d/BoxP.h>
00062
00063
00064
00065
00066
00067
00068
00069 static XtResource resources[] = {
00070 { XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
00071 XtOffsetOf(BoxRec, box.h_space),
00072 XtRImmediate, (XtPointer)4 },
00073 { XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
00074 XtOffsetOf(BoxRec, box.v_space),
00075 XtRImmediate, (XtPointer)4 },
00076 { XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
00077 XtOffsetOf(BoxRec, box.orientation),
00078 XtRImmediate, (XtPointer)XtorientVertical },
00079 };
00080
00081
00082
00083
00084
00085
00086
00087 static void ClassInitialize();
00088 static void Initialize();
00089 static void Realize();
00090 static void Resize();
00091 static Boolean SetValues();
00092 static XtGeometryResult GeometryManager();
00093 static void ChangeManaged();
00094 static XtGeometryResult PreferredSize();
00095
00096 BoxClassRec boxClassRec = {
00097 {
00098
00099 (WidgetClass) &compositeClassRec,
00100 "Box",
00101 sizeof(BoxRec),
00102 ClassInitialize,
00103 NULL,
00104 FALSE,
00105 Initialize,
00106 NULL,
00107 Realize,
00108 NULL,
00109 0,
00110 resources,
00111 XtNumber(resources),
00112 NULLQUARK,
00113 TRUE,
00114 TRUE,
00115 TRUE,
00116 FALSE,
00117 NULL,
00118 Resize,
00119 NULL,
00120 SetValues,
00121 NULL,
00122 XtInheritSetValuesAlmost,
00123 NULL,
00124 NULL,
00125 XtVersion,
00126 NULL,
00127 NULL,
00128 PreferredSize,
00129 XtInheritDisplayAccelerator,
00130 NULL
00131 },{
00132
00133 GeometryManager,
00134 ChangeManaged,
00135 XtInheritInsertChild,
00136 XtInheritDeleteChild,
00137 NULL
00138 },{
00139
00140 0,
00141 }
00142 };
00143
00144 WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec;
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 static void DoLayout(bbw, width, height, reply_width, reply_height, position)
00161 BoxWidget bbw;
00162 Dimension width, height;
00163 Dimension *reply_width, *reply_height;
00164 Boolean position;
00165 {
00166 Boolean vbox = (bbw->box.orientation == XtorientVertical);
00167 Cardinal i;
00168 Dimension w, h;
00169 Dimension lw, lh;
00170 Dimension bw, bh;
00171 Dimension h_space;
00172 Widget widget;
00173 int num_mapped_children = 0;
00174
00175
00176 h_space = bbw->box.h_space;
00177
00178 w = 0;
00179 for (i = 0; i < bbw->composite.num_children; i++) {
00180 if ( bbw->composite.children[i]->core.width > w )
00181 w = bbw->composite.children[i]->core.width;
00182 }
00183 w += h_space;
00184 if ( w > width ) width = w;
00185 h = bbw->box.v_space;
00186
00187
00188 lh = 0;
00189 lw = h_space;
00190
00191 for (i = 0; i < bbw->composite.num_children; i++) {
00192 widget = bbw->composite.children[i];
00193 if (widget->core.managed) {
00194 if (widget->core.mapped_when_managed) num_mapped_children++;
00195
00196 bw = widget->core.width + 2*widget->core.border_width + h_space;
00197 if ((Dimension)(lw + bw) > width) {
00198 if (lw > h_space) {
00199
00200
00201
00202 AssignMax(w, lw);
00203 if (vbox) {
00204 h += lh + bbw->box.v_space;
00205 lh = 0;
00206 lw = h_space;
00207 }
00208 }
00209 else if (!position) {
00210
00211 DoLayout(bbw, lw + bw, height, reply_width,
00212 reply_height, position);
00213 return;
00214 }
00215 }
00216 if (position && (lw != (Dimension)widget->core.x || h != (Dimension)widget->core.y)) {
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 if (XtIsRealized(widget) && widget->core.mapped_when_managed)
00230 XUnmapWindow( XtDisplay(widget), XtWindow(widget) );
00231 XtMoveWidget(widget, (int)lw, (int)h);
00232 }
00233 lw += bw;
00234 bh = widget->core.height + 2*widget->core.border_width;
00235 AssignMax(lh, bh);
00236 }
00237 }
00238
00239 if (!vbox && width && lw > width && lh < height) {
00240
00241 Dimension sw = lw, sh = lh;
00242 Dimension width_needed = 0;
00243 XtOrientation orientation = bbw->box.orientation;
00244 bbw->box.orientation = XtorientVertical;
00245 while (sh < height && sw > width) {
00246 width_needed = sw;
00247 DoLayout(bbw, sw-1, height, &sw, &sh, False);
00248 }
00249 if (sh < height) width_needed = sw;
00250 if (width_needed != lw) {
00251 DoLayout(bbw,width_needed,height,reply_width,reply_height,position);
00252 bbw->box.orientation = orientation;
00253 return;
00254 }
00255 bbw->box.orientation = orientation;
00256 }
00257 if ( vbox && ( ( width < w ) || ( width < lw ) ) ) {
00258 AssignMax(w, lw);
00259 DoLayout( bbw, w, height, reply_width, reply_height, position );
00260 return;
00261 }
00262 if (position && XtIsRealized((Widget)bbw)) {
00263 if (bbw->composite.num_children == num_mapped_children)
00264 XMapSubwindows( XtDisplay((Widget)bbw), XtWindow((Widget)bbw) );
00265 else {
00266 int i = bbw->composite.num_children;
00267 Widget *childP = bbw->composite.children;
00268 for (; i > 0; childP++, i--)
00269 if (XtIsRealized(*childP) && XtIsManaged(*childP) &&
00270 (*childP)->core.mapped_when_managed)
00271 XtMapWidget(*childP);
00272 }
00273 }
00274
00275
00276 if (lw > h_space) {
00277 AssignMax(w, lw);
00278 h += lh + bbw->box.v_space;
00279 }
00280
00281 *reply_width = Max(w, 1);
00282 *reply_height = Max(h, 1);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 static XtGeometryResult PreferredSize(widget, constraint, preferred)
00292 Widget widget;
00293 XtWidgetGeometry *constraint, *preferred;
00294 {
00295 BoxWidget w = (BoxWidget)widget;
00296 Dimension width ;
00297 Dimension preferred_width = w->box.preferred_width;
00298 Dimension preferred_height = w->box.preferred_height;
00299
00300 constraint->request_mode &= CWWidth | CWHeight;
00301
00302 if (constraint->request_mode == 0)
00303
00304 return XtGeometryYes;
00305
00306 if (constraint->request_mode == w->box.last_query_mode &&
00307 (!(constraint->request_mode & CWWidth) ||
00308 constraint->width == w->box.last_query_width) &&
00309 (!(constraint->request_mode & CWHeight) ||
00310 constraint->height == w->box.last_query_height)) {
00311
00312 preferred->request_mode = CWWidth | CWHeight;
00313 preferred->width = preferred_width;
00314 preferred->height = preferred_height;
00315 if (constraint->request_mode == (CWWidth | CWHeight) &&
00316 constraint->width == preferred_width &&
00317 constraint->height == preferred_height)
00318 return XtGeometryYes;
00319 else
00320 return XtGeometryAlmost;
00321 }
00322
00323
00324
00325
00326
00327
00328 w->box.last_query_mode = constraint->request_mode;
00329 w->box.last_query_width = constraint->width;
00330 w->box.last_query_height= constraint->height;
00331
00332 if (constraint->request_mode & CWWidth)
00333 width = constraint->width;
00334 else {
00335
00336 width = 0;
00337 constraint->width = 65535;
00338 }
00339
00340
00341
00342
00343
00344 DoLayout(w, width, (Dimension)0,
00345 &preferred_width, &preferred_height, FALSE);
00346
00347 if (constraint->request_mode & CWHeight &&
00348 preferred_height > constraint->height) {
00349
00350 if (preferred_width > constraint->width) {
00351
00352 }
00353 else {
00354 width = preferred_width;
00355 do {
00356 width *= 2;
00357 if (width > constraint->width) width = constraint->width;
00358 DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE);
00359 } while (preferred_height > constraint->height &&
00360 width < constraint->width);
00361 if (width != constraint->width) {
00362 do {
00363 width = preferred_width;
00364 DoLayout(w, preferred_width-1, 0,
00365 &preferred_width, &preferred_height, FALSE);
00366 } while (preferred_height < constraint->height);
00367
00368 DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE);
00369 }
00370 }
00371 }
00372
00373 preferred->request_mode = CWWidth | CWHeight;
00374 preferred->width = w->box.preferred_width = preferred_width;
00375 preferred->height = w->box.preferred_height = preferred_height;
00376
00377 if (constraint->request_mode == (CWWidth|CWHeight)
00378 && constraint->width == preferred_width
00379 && constraint->height == preferred_height)
00380 return XtGeometryYes;
00381 else
00382 return XtGeometryAlmost;
00383
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 static void Resize(w)
00393 Widget w;
00394 {
00395 Dimension junk;
00396
00397 DoLayout((BoxWidget)w, w->core.width, w->core.height, &junk, &junk, TRUE);
00398
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 static Boolean TryNewLayout(bbw)
00411 BoxWidget bbw;
00412 {
00413 Dimension preferred_width, preferred_height;
00414 Dimension proposed_width, proposed_height;
00415 int iterations;
00416
00417 DoLayout( bbw, bbw->core.width, bbw->core.height,
00418 &preferred_width, &preferred_height, FALSE );
00419
00420
00421
00422
00423
00424 if ((bbw->core.width == preferred_width) &&
00425 (bbw->core.height == preferred_height)) {
00426
00427 return (TRUE);
00428 }
00429
00430
00431 iterations = 0;
00432 proposed_width = preferred_width;
00433 proposed_height = preferred_height;
00434 do {
00435 switch (XtMakeResizeRequest((Widget)bbw,proposed_width,proposed_height,
00436 &proposed_width, &proposed_height))
00437 {
00438 case XtGeometryYes:
00439 return (TRUE);
00440
00441 case XtGeometryNo:
00442 if (iterations > 0)
00443
00444 DoLayout( bbw, bbw->core.width, bbw->core.height,
00445 &preferred_width, &preferred_height, FALSE );
00446 if ((preferred_width <= bbw->core.width) &&
00447 (preferred_height <= bbw->core.height))
00448 return (TRUE);
00449 else
00450 return (FALSE);
00451
00452 case XtGeometryAlmost:
00453 if (proposed_height >= preferred_height &&
00454 proposed_width >= preferred_width) {
00455
00456
00457
00458
00459
00460
00461
00462
00463 (void) XtMakeResizeRequest( (Widget)bbw,
00464 proposed_width, proposed_height,
00465 &proposed_width, &proposed_height);
00466 return(TRUE);
00467 }
00468 else if (proposed_width != preferred_width) {
00469
00470 DoLayout(bbw, proposed_width, 0,
00471 &preferred_width, &preferred_height, FALSE);
00472 proposed_height = preferred_height;
00473 }
00474 else {
00475 XtWidgetGeometry constraints, reply;
00476 constraints.request_mode = CWHeight;
00477 constraints.height = proposed_height;
00478 (void)PreferredSize((Widget)bbw, &constraints, &reply);
00479 proposed_width = preferred_width;
00480 }
00481 break;
00482
00483 case XtGeometryDone:
00484 default:
00485 break;
00486 }
00487 iterations++;
00488 } while (iterations < 10);
00489 return (FALSE);
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 static XtGeometryResult GeometryManager(w, request, reply)
00502 Widget w;
00503 XtWidgetGeometry *request;
00504 XtWidgetGeometry *reply;
00505
00506 {
00507 Dimension width, height, borderWidth;
00508 BoxWidget bbw;
00509
00510
00511 if ((request->request_mode & CWX && request->x != w->core.x) ||
00512 (request->request_mode & CWY && request->y != w->core.y))
00513 return (XtGeometryNo);
00514
00515
00516 if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
00517
00518
00519 if ((request->request_mode & CWWidth) == 0)
00520 request->width = w->core.width;
00521 if ((request->request_mode & CWHeight) == 0)
00522 request->height = w->core.height;
00523 if ((request->request_mode & CWBorderWidth) == 0)
00524 request->border_width = w->core.border_width;
00525
00526
00527 width = w->core.width;
00528 height = w->core.height;
00529 borderWidth = w->core.border_width;
00530 w->core.width = request->width;
00531 w->core.height = request->height;
00532 w->core.border_width = request->border_width;
00533
00534
00535
00536
00537
00538 bbw = (BoxWidget) w->core.parent;
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 if (TryNewLayout(bbw)) {
00549
00550 (*XtClass((Widget)bbw)->core_class.resize)((Widget)bbw);
00551 return (XtGeometryYes);
00552 } else {
00553
00554 w->core.width = width;
00555 w->core.height = height;
00556 w->core.border_width = borderWidth;
00557 return (XtGeometryNo);
00558 }
00559 };
00560
00561
00562 return (XtGeometryYes);
00563 }
00564
00565 static void ChangeManaged(w)
00566 Widget w;
00567 {
00568
00569 (void) TryNewLayout((BoxWidget)w);
00570 Resize(w);
00571 }
00572
00573 static void ClassInitialize()
00574 {
00575 XawInitializeWidgetSet();
00576 XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
00577 (XtConvertArgList)NULL, (Cardinal)0 );
00578 }
00579
00580
00581 static void Initialize(request, new, args, num_args)
00582 Widget request, new;
00583 ArgList args;
00584 Cardinal *num_args;
00585 {
00586 BoxWidget newbbw = (BoxWidget)new;
00587
00588 newbbw->box.last_query_mode = CWWidth | CWHeight;
00589 newbbw->box.last_query_width = newbbw->box.last_query_height = 0;
00590 newbbw->box.preferred_width = Max(newbbw->box.h_space, 1);
00591 newbbw->box.preferred_height = Max(newbbw->box.v_space, 1);
00592
00593 if (newbbw->core.width == 0)
00594 newbbw->core.width = newbbw->box.preferred_width;
00595
00596 if (newbbw->core.height == 0)
00597 newbbw->core.height = newbbw->box.preferred_height;
00598
00599 }
00600
00601 static void Realize(w, valueMask, attributes)
00602 Widget w;
00603 Mask *valueMask;
00604 XSetWindowAttributes *attributes;
00605 {
00606 attributes->bit_gravity = NorthWestGravity;
00607 *valueMask |= CWBitGravity;
00608
00609 XtCreateWindow( w, (unsigned)InputOutput, (Visual *)CopyFromParent,
00610 *valueMask, attributes);
00611 }
00612
00613
00614 static Boolean SetValues(current, request, new, args, num_args)
00615 Widget current, request, new;
00616 ArgList args;
00617 Cardinal *num_args;
00618 {
00619
00620
00621 return False;
00622 }