|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcsid[] = "$Header: ButtonBox.c,v 1.13 87/09/13 20:35:58 newman Exp $"; ! 3: #endif lint ! 4: ! 5: /* ! 6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 7: * ! 8: * All Rights Reserved ! 9: * ! 10: * Permission to use, copy, modify, and distribute this software and its ! 11: * documentation for any purpose and without fee is hereby granted, ! 12: * provided that the above copyright notice appear in all copies and that ! 13: * both that copyright notice and this permission notice appear in ! 14: * supporting documentation, and that the name of Digital Equipment ! 15: * Corporation not be used in advertising or publicity pertaining to ! 16: * distribution of the software without specific, written prior permission. ! 17: * ! 18: * ! 19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 25: * SOFTWARE. ! 26: */ ! 27: /* ! 28: * ButtonBox.c - Button box composite widget ! 29: * ! 30: * Author: Joel McCormack ! 31: * Digital Equipment Corporation ! 32: * Western Research Laboratory ! 33: * Date: Mon Aug 31 1987 ! 34: * ! 35: */ ! 36: ! 37: #include "Intrinsic.h" ! 38: #include "ButtonBox.h" ! 39: #include "ButtonBoxP.h" ! 40: #include "Atoms.h" ! 41: #include "Misc.h" ! 42: ! 43: /**************************************************************** ! 44: * ! 45: * ButtonBox Resources ! 46: * ! 47: ****************************************************************/ ! 48: ! 49: static XtResource resources[] = { ! 50: {XtNhSpace, XtCHSpace, XrmRInt, sizeof(int), ! 51: XtOffset(ButtonBoxWidget, button_box.h_space), XtRString, "4"}, ! 52: {XtNvSpace, XtCVSpace, XrmRInt, sizeof(int), ! 53: XtOffset(ButtonBoxWidget, button_box.v_space), XtRString, "4"}, ! 54: }; ! 55: ! 56: /**************************************************************** ! 57: * ! 58: * Full class record constant ! 59: * ! 60: ****************************************************************/ ! 61: ! 62: static void Initialize(); ! 63: static void Realize(); ! 64: static void Resize(); ! 65: static Boolean SetValues(); ! 66: static XtGeometryResult GeometryManager(); ! 67: static void ChangeManaged(); ! 68: static void ClassInitialize(); ! 69: ! 70: ButtonBoxClassRec buttonBoxClassRec = { ! 71: { ! 72: /* core_class fields */ ! 73: /* superclass */ (WidgetClass) &compositeClassRec, ! 74: /* class_name */ "ButtonBox", ! 75: /* widget_size */ sizeof(ButtonBoxRec), ! 76: /* class_initialize */ ClassInitialize, ! 77: /* class_inited */ FALSE, ! 78: /* initialize */ Initialize, ! 79: /* realize */ Realize, ! 80: /* actions */ NULL, ! 81: /* num_actions */ 0, ! 82: /* resources */ resources, ! 83: /* num_resources */ XtNumber(resources), ! 84: /* xrm_class */ NULLQUARK, ! 85: /* compress_motion */ TRUE, ! 86: /* compress_exposure */ TRUE, ! 87: /* visible_interest */ FALSE, ! 88: /* destroy */ NULL, ! 89: /* resize */ Resize, ! 90: /* expose */ NULL, ! 91: /* set_values */ SetValues, ! 92: /* accept_focus */ NULL ! 93: },{ ! 94: /* composite_class fields */ ! 95: /* geometry_manager */ GeometryManager, ! 96: /* change_managed */ ChangeManaged, ! 97: /* insert_child */ NULL, /* Inherit from superclass */ ! 98: /* delete_child */ NULL, /* Inherit from superclass */ ! 99: /* move_focus_to_next */ NULL, ! 100: /* move_focus_to_prev */ NULL ! 101: },{ ! 102: /* mumble */ 0 /* Make C compiler happy */ ! 103: } ! 104: }; ! 105: ! 106: WidgetClass buttonBoxWidgetClass = (WidgetClass)&buttonBoxClassRec; ! 107: ! 108: ! 109: /**************************************************************** ! 110: * ! 111: * Private Routines ! 112: * ! 113: ****************************************************************/ ! 114: ! 115: static void ClassInitialize() ! 116: { ! 117: CompositeWidgetClass superclass; ! 118: ButtonBoxWidgetClass myclass; ! 119: ! 120: myclass = (ButtonBoxWidgetClass) buttonBoxWidgetClass; ! 121: superclass = (CompositeWidgetClass) myclass->core_class.superclass; ! 122: ! 123: /* Inherit insert_child and delete_child from Composite */ ! 124: myclass->composite_class.insert_child = ! 125: superclass->composite_class.insert_child; ! 126: myclass->composite_class.delete_child = ! 127: superclass->composite_class.delete_child; ! 128: } ! 129: ! 130: /* ! 131: * ! 132: * Do a layout, either actually assigning positions, or just calculating size. ! 133: * Returns TRUE on success; FALSE if it couldn't make things fit. ! 134: * ! 135: */ ! 136: ! 137: /* ARGSUSED */ ! 138: static DoLayout(bbw, width, height, replyWidth, replyHeight, position) ! 139: ButtonBoxWidget bbw; ! 140: Dimension width, height; ! 141: Dimension *replyWidth, *replyHeight; /* RETURN */ ! 142: Boolean position; /* actually reposition the windows? */ ! 143: { ! 144: Cardinal i; ! 145: Dimension w, h; /* Width and height needed for button box */ ! 146: Dimension lw, lh; /* Width and height needed for current line */ ! 147: Dimension bw, bh; /* Width and height needed for current button */ ! 148: Dimension h_space; /* Local copy of bbw->buttonBox.h_space */ ! 149: Widget widget; /* Current button */ ! 150: ! 151: /* ButtonBox width and height */ ! 152: h_space = bbw->button_box.h_space; ! 153: w = h_space; ! 154: h = bbw->button_box.v_space; ! 155: ! 156: /* Line width and height */ ! 157: lh = 0; ! 158: lw = h_space; ! 159: ! 160: for (i = 0; i < bbw->composite.num_children; i++) { ! 161: widget = bbw->composite.children[i]; ! 162: if (widget->core.managed) { ! 163: /* Compute button width */ ! 164: bw = widget->core.width + 2*widget->core.border_width + h_space; ! 165: if ((lw + bw > width) && (lw > h_space)) { ! 166: /* At least one button on this line, and can't fit any more. ! 167: Start new line */ ! 168: AssignMax(w, lw); ! 169: h += lh + bbw->button_box.v_space; ! 170: lh = 0; ! 171: lw = h_space; ! 172: } ! 173: if (position && (lw != widget->core.x || h != widget->core.y)) { ! 174: XtMoveWidget(bbw->composite.children[i], (int)lw, (int)h); ! 175: } ! 176: lw += bw; ! 177: bh = widget->core.height + 2*widget->core.border_width; ! 178: AssignMax(lh, bh); ! 179: } /* if managed */ ! 180: } /* for */ ! 181: ! 182: /* Finish off last line */ ! 183: if (lw > h_space) { ! 184: AssignMax(w, lw); ! 185: h += lh + bbw->button_box.v_space; ! 186: } ! 187: ! 188: *replyWidth = w; ! 189: *replyHeight = h; ! 190: } ! 191: ! 192: /* ! 193: * ! 194: * Calculate preferred size, given constraining box ! 195: * ! 196: */ ! 197: ! 198: static Boolean PreferredSize(bbw, width, height, replyWidth, replyHeight) ! 199: ButtonBoxWidget bbw; ! 200: Dimension width, height; ! 201: Dimension *replyWidth, *replyHeight; ! 202: { ! 203: DoLayout(bbw, width, height, replyWidth, replyHeight, FALSE); ! 204: return ((*replyWidth <= width) && (*replyHeight <= height)); ! 205: } ! 206: ! 207: /* ! 208: * ! 209: * Actually layout the button box ! 210: * ! 211: */ ! 212: ! 213: static void Resize(bbw) ! 214: ButtonBoxWidget bbw; ! 215: { ! 216: Dimension junk; ! 217: ! 218: DoLayout(bbw, bbw->core.width, bbw->core.height, &junk, &junk, TRUE); ! 219: } /* Resize */ ! 220: ! 221: /* ! 222: * ! 223: * Try to do a new layout within the current width and height; ! 224: * if that fails try to do it within the box returned by PreferredSize. ! 225: * ! 226: * TryNewLayout just says if it's possible, and doesn't actually move the kids ! 227: */ ! 228: ! 229: static Boolean TryNewLayout(bbw) ! 230: ButtonBoxWidget bbw; ! 231: { ! 232: Dimension width, height; ! 233: ! 234: if (!PreferredSize(bbw, bbw->core.width, bbw->core.height, &width, &height)) ! 235: (void) PreferredSize(bbw, width, height, &width, &height); ! 236: ! 237: if ((bbw->core.width == width) && (bbw->core.height == height)) { ! 238: /* Same size */ ! 239: return (TRUE); ! 240: } ! 241: ! 242: /* let's see if our parent will go for a new size. */ ! 243: switch (XtMakeResizeRequest((Widget) bbw, width, height, &width, &height)) { ! 244: ! 245: case XtGeometryYes: ! 246: return (TRUE); ! 247: ! 248: case XtGeometryNo: ! 249: return (FALSE); ! 250: ! 251: case XtGeometryAlmost: ! 252: if (! PreferredSize(bbw, width, height, &width, &height)) ! 253: return (FALSE); ! 254: (void) XtMakeResizeRequest((Widget) bbw, width, height, ! 255: &width, &height); ! 256: return (TRUE); ! 257: } ! 258: } ! 259: ! 260: /* ! 261: * ! 262: * Geometry Manager ! 263: * ! 264: */ ! 265: ! 266: /*ARGSUSED*/ ! 267: static XtGeometryResult GeometryManager(w, request, reply) ! 268: Widget w; ! 269: XtWidgetGeometry *request; ! 270: XtWidgetGeometry *reply; /* RETURN */ ! 271: ! 272: { ! 273: Dimension width, height, borderWidth, junk; ! 274: ButtonBoxWidget bbw; ! 275: ! 276: /* Position request always denied */ ! 277: if (request->request_mode & (CWX | CWY)) ! 278: return (XtGeometryNo); ! 279: ! 280: /* Size changes must see if the new size can be accomodated */ ! 281: if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) { ! 282: ! 283: /* Make all three fields in the request valid */ ! 284: if ((request->request_mode & CWWidth) == 0) ! 285: request->width = w->core.width; ! 286: if ((request->request_mode & CWHeight) == 0) ! 287: request->height = w->core.height; ! 288: if ((request->request_mode & CWBorderWidth) == 0) ! 289: request->border_width = w->core.border_width; ! 290: ! 291: /* Save current size and set to new size */ ! 292: width = w->core.width; ! 293: height = w->core.height; ! 294: borderWidth = w->core.border_width; ! 295: w->core.width = request->width; ! 296: w->core.height = request->height; ! 297: w->core.border_width = request->border_width; ! 298: ! 299: /* Decide if new layout works: (1) new button is smaller, ! 300: (2) new button fits in existing ButtonBox, (3) ButtonBox can be ! 301: expanded to allow new button to fit */ ! 302: ! 303: bbw = (ButtonBoxWidget) w->core.parent; ! 304: if (((request->width + request->border_width <= width + borderWidth) && ! 305: (request->height + request->border_width <= height + borderWidth)) ! 306: || PreferredSize(bbw, bbw->core.width, bbw->core.height, &junk, &junk) ! 307: || TryNewLayout(bbw)) { ! 308: /* Fits in existing or new space, relayout */ ! 309: Resize(bbw); ! 310: return (XtGeometryYes); ! 311: } else { ! 312: /* Cannot satisfy request, change back to original geometry */ ! 313: w->core.width = width; ! 314: w->core.height = height; ! 315: w->core.border_width = borderWidth; ! 316: return (XtGeometryNo); ! 317: } ! 318: }; /* if any size changes requested */ ! 319: ! 320: /* Any stacking changes don't make a difference, so allow if that's all */ ! 321: return (XtGeometryYes); ! 322: } ! 323: ! 324: static void ChangeManaged(bbw) ! 325: ButtonBoxWidget bbw; ! 326: { ! 327: /* Reconfigure the button box */ ! 328: (void) TryNewLayout(bbw); ! 329: Resize(bbw); ! 330: } ! 331: ! 332: static void Initialize(request, new, args, num_args) ! 333: ButtonBoxWidget request, new; ! 334: ArgList args; ! 335: Cardinal num_args; ! 336: { ! 337: /* ||| What are consequences of letting height, width be 0? If okay, then ! 338: Initialize can be NULL */ ! 339: ! 340: if (new->core.width == 0) ! 341: new->core.width = ! 342: ((new->button_box.h_space != 0) ? new->button_box.h_space : 10); ! 343: if (new->core.height == 0) ! 344: new->core.height = ! 345: ((new->button_box.v_space != 0) ? new->button_box.v_space : 10); ! 346: } /* Initialize */ ! 347: ! 348: /* ||| Should Realize just return a modified mask and attributes? Or will some ! 349: of the other parameters change from class to class? */ ! 350: static void Realize(w, valueMask, attributes) ! 351: register Widget w; ! 352: Mask valueMask; ! 353: XSetWindowAttributes *attributes; ! 354: { ! 355: attributes->bit_gravity = NorthWestGravity; ! 356: valueMask |= CWBitGravity; ! 357: ! 358: w->core.window = ! 359: XCreateWindow(XtDisplay(w), XtWindow(w->core.parent), ! 360: w->core.x, w->core.y, w->core.width, w->core.height, ! 361: w->core.border_width, w->core.depth, ! 362: InputOutput, (Visual *)CopyFromParent, ! 363: valueMask, attributes); ! 364: } /* Realize */ ! 365: ! 366: /* ! 367: * ! 368: * Set Values ! 369: * ! 370: */ ! 371: ! 372: static Boolean SetValues (current, request, new, last) ! 373: ButtonBoxWidget current, request, new; ! 374: Boolean last; ! 375: { ! 376: /* ||| Old code completely bogus, need background, etc., then ! 377: XtMakeGeometryRequest, then relayout */ ! 378: return (FALSE); ! 379: } ! 380:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.