|
|
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.