]> code.delx.au - gnu-emacs/blob - lwlib/lwlib-Xolmb.c
*** empty log message ***
[gnu-emacs] / lwlib / lwlib-Xolmb.c
1 /* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
2 Copyright (C) 1993 Lucid, Inc.
3
4 This file is part of the Lucid Widget Library.
5
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <X11/IntrinsicP.h>
22 #include <X11/Intrinsic.h>
23 #include <X11/CompositeP.h>
24 #include <X11/Composite.h>
25 #include "lwlib-Xol-mbP.h"
26 #include "lwlib-Xol-mb.h"
27
28 #define HORIZ_SPACING 4
29 #define VERT_SPACING 4
30
31 static void Initialize();
32 static void Resize();
33 static void ChangeManaged();
34 static Boolean SetValues();
35 static XtGeometryResult GeometryManager();
36 static XtGeometryResult PreferredSize();
37 static void do_layout();
38 static XtGeometryResult try_layout();
39
40 lwMenuBarClassRec lwMenubarClassRec =
41 {
42 {
43 /* core_class members */
44
45 (WidgetClass) &compositeClassRec, /* superclass */
46 "Menubar", /* class_name */
47 sizeof(lwMenuBarRec), /* widget_size */
48 NULL, /* class_initialize */
49 NULL, /* class_part_initialize */
50 FALSE, /* class_inited */
51 Initialize, /* initialize */
52 NULL, /* initialize_hook */
53 XtInheritRealize, /* realize */
54 NULL, /* actions */
55 0, /* num_actions */
56 NULL, /* resources */
57 0, /* num_resources */
58 NULLQUARK, /* xrm_class */
59 TRUE, /* compress_motion */
60 XtExposeCompressMaximal, /* compress_exposure */
61 TRUE, /* compress_enterleave */
62 FALSE, /* visible_interest */
63 NULL, /* destroy */
64 Resize, /* resize */
65 NULL, /* expose */
66 NULL, /* set_values */
67 NULL, /* set_values_hook */
68 XtInheritSetValuesAlmost, /* set_values_almost */
69 NULL, /* get_values_hook */
70 NULL, /* accept_focus */
71 XtVersion, /* version */
72 NULL, /* callback_private */
73 NULL, /* tm_table */
74 PreferredSize, /* query_geometry */
75 NULL, /* display_accelerator */
76 NULL, /* extension */
77 },
78 {
79 /* composite_class members */
80
81 GeometryManager, /* geometry_manager */
82 ChangeManaged, /* change_managed */
83 XtInheritInsertChild, /* insert_child */
84 XtInheritDeleteChild, /* delete_child */
85 NULL, /* extension */
86 },
87 {
88 /* Menubar class members */
89
90 0, /* empty */
91 }
92 };
93 WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
94
95
96 static void Initialize (request, new)
97 lwMenuBarWidget request, new;
98 {
99 if (request->core.width <= 0)
100 new->core.width = 1;
101 if (request->core.height <= 0)
102 new->core.height = 23;
103 }
104
105 static void
106 Resize (w)
107 lwMenuBarWidget w;
108 {
109 do_layout(w);
110 }
111
112 static void
113 do_layout (parent)
114 lwMenuBarWidget parent;
115 {
116 Widget child;
117 int cnt;
118 int managed_children = 0;
119 int managed_width = 0;
120 int new_pos = 0;
121
122 /*
123 * Determine number of children which will fit on one line.
124 * For now we ignore the rest, making sure they are unmanaged.
125 */
126
127 cnt = 0;
128 while ((cnt < (int) parent->composite.num_children) &&
129 (managed_width < (int) parent->core.width))
130 {
131 child = parent->composite.children[cnt++];
132 managed_children++;
133 managed_width += child->core.width + child->core.border_width * 2 +
134 HORIZ_SPACING;
135 }
136
137 if (managed_width > (int) parent->core.width)
138 managed_children--;
139
140 /*
141 * Correct positioning of children.
142 */
143
144 cnt = 0;
145 while (managed_children)
146 {
147 child = parent->composite.children[cnt++];
148
149 if (!child->core.managed)
150 XtManageChild (child);
151
152 if ((child->core.x != new_pos) || (child->core.y != 0))
153 XtMoveWidget (child, new_pos, 0);
154 new_pos += child->core.width + child->core.border_width * 2 +
155 HORIZ_SPACING;
156
157 managed_children--;
158 }
159
160 /*
161 * Make sure all remaining children are unmanaged.
162 */
163
164 while (cnt < parent->composite.num_children)
165 {
166 child = parent->composite.children[cnt];
167
168 if (child->core.managed)
169 XtUnmanageChild (child);
170
171 if ((child->core.x != parent->core.width) ||
172 (child->core.y != parent->core.height))
173 XtMoveWidget (child, parent->core.width, parent->core.height);
174
175 cnt++;
176 }
177 }
178
179
180 static XtGeometryResult
181 PreferredSize (w, request, preferred)
182 lwMenuBarWidget w;
183 XtWidgetGeometry *request, *preferred;
184 {
185 Widget child;
186 int cnt;
187
188 /*
189 * If no changes are being made to the width or height, just agree.
190 */
191
192 if (!(request->request_mode & CWWidth) &&
193 !(request->request_mode & CWHeight))
194 return (XtGeometryYes);
195
196 /*
197 * Right now assume everything goes in one row. Calculate the
198 * minimum required width and height.
199 */
200
201 preferred->width = 0;
202 preferred->height = 0;
203
204 for (cnt = 0; cnt < w->composite.num_children; cnt++)
205 {
206 child = w->composite.children[cnt];
207 if (child->core.managed)
208 {
209 preferred->width += child->core.width + child->core.border_width*2 +
210 HORIZ_SPACING;
211 if (preferred->height < (Dimension) (child->core.height +
212 child->core.border_width * 2))
213 preferred->height = child->core.height +
214 child->core.border_width * 2;
215 }
216 }
217
218 preferred->request_mode = CWWidth | CWHeight;
219
220 /*
221 * Case: both height and width requested
222 */
223
224 if ((request->request_mode & CWWidth) &&
225 (request->request_mode & CWHeight))
226 {
227 /*
228 * Ok if same or bigger.
229 */
230
231 if (preferred->width <= request->width &&
232 preferred->height <= request->height)
233 {
234 preferred->width = request->width;
235 return (XtGeometryYes);
236 }
237
238 /*
239 * If both dimensions are too small, say no.
240 */
241
242 else
243 if (preferred->width > request->width &&
244 preferred->height > request->height)
245 return (XtGeometryNo);
246
247 /*
248 * Otherwise one must be right, so say almost.
249 */
250
251 else
252 return (XtGeometryAlmost);
253 }
254
255 /*
256 * If only one dimension is requested, either its OK or it isn't.
257 */
258
259 else
260 {
261 if (request->request_mode & CWWidth)
262 {
263 if (preferred->width <= request->width)
264 {
265 preferred->width = request->width;
266 return (XtGeometryYes);
267 }
268 else
269 return (XtGeometryNo);
270 }
271 else if (request->request_mode & CWHeight)
272 {
273 if (preferred->height <= request->height)
274 {
275 return (XtGeometryYes);
276 }
277 else
278 return (XtGeometryNo);
279 }
280
281 return (XtGeometryYes);
282 }
283 }
284
285
286 static XtGeometryResult
287 GeometryManager (w, request, reply)
288 Widget w;
289 XtWidgetGeometry *request;
290 XtWidgetGeometry *reply;
291 {
292
293 lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent;
294
295 /*
296 * If the widget wants to move, just say no.
297 */
298
299 if ((request->request_mode & CWX && request->x != w->core.x) ||
300 (request->request_mode & CWY && request->y != w->core.y))
301 return (XtGeometryNo);
302
303 /*
304 * Since everything "fits" for now, grant all requests.
305 */
306
307 if (request->request_mode & CWWidth)
308 w->core.width = request->width;
309 if (request->request_mode & CWHeight)
310 w->core.height = request->height;
311 if (request->request_mode & CWBorderWidth)
312 w->core.border_width = request->border_width;
313
314 do_layout (parent);
315 return (XtGeometryYes);
316 }
317
318
319 static XtGeometryResult
320 try_layout (parent)
321 lwMenuBarWidget parent;
322 {
323 Widget child;
324 int cnt;
325 int managed_children = 0;
326 int managed_width = 0;
327 int new_pos = 0;
328
329 /*
330 * Determine number of children which will fit on one line.
331 * For now we ignore the rest, making sure they are unmanaged.
332 */
333
334 cnt = 0;
335 while ((cnt < (int) parent->composite.num_children) &&
336 (managed_width < (int) parent->core.width))
337 {
338 child = parent->composite.children[cnt++];
339 if (child->core.managed)
340 {
341 managed_children++;
342 managed_width += child->core.width + child->core.border_width * 2 +
343 HORIZ_SPACING;
344 }
345 }
346
347 if (managed_width > (int) parent->core.width)
348 return (XtGeometryNo);
349 else
350 return (XtGeometryYes);
351 }
352
353
354
355 static void
356 ChangeManaged (w)
357 lwMenuBarWidget w;
358 {
359 XtGeometryResult result;
360
361 result = try_layout (w);
362
363 if (result != XtGeometryYes)
364 {
365 XtUnmanageChild (w->composite.children[w->composite.num_children - 1]);
366 XtMoveWidget (w->composite.children[w->composite.num_children-1],
367 w->core.width, w->core.height);
368 }
369
370 do_layout (w);
371 }