new version
[emacs.git] / lwlib / lwlib-Xolmb.c
bloba49e8ab54057fa04c5b79d502ec7a945a183a25c
1 /* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
2 Copyright (C) 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
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.
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.
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. */
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"
28 #define HORIZ_SPACING 4
29 #define VERT_SPACING 4
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();
40 lwMenuBarClassRec lwMenubarClassRec =
43 /* core_class members */
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 */
79 /* composite_class members */
81 GeometryManager, /* geometry_manager */
82 ChangeManaged, /* change_managed */
83 XtInheritInsertChild, /* insert_child */
84 XtInheritDeleteChild, /* delete_child */
85 NULL, /* extension */
88 /* Menubar class members */
90 0, /* empty */
93 WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
96 static void Initialize (request, new)
97 lwMenuBarWidget request, new;
99 if (request->core.width <= 0)
100 new->core.width = 1;
101 if (request->core.height <= 0)
102 new->core.height = 23;
105 static void
106 Resize (w)
107 lwMenuBarWidget w;
109 do_layout(w);
112 static void
113 do_layout (parent)
114 lwMenuBarWidget parent;
116 Widget child;
117 int cnt;
118 int managed_children = 0;
119 int managed_width = 0;
120 int new_pos = 0;
123 * Determine number of children which will fit on one line.
124 * For now we ignore the rest, making sure they are unmanaged.
127 cnt = 0;
128 while ((cnt < (int) parent->composite.num_children) &&
129 (managed_width < (int) parent->core.width))
131 child = parent->composite.children[cnt++];
132 managed_children++;
133 managed_width += child->core.width + child->core.border_width * 2 +
134 HORIZ_SPACING;
137 if (managed_width > (int) parent->core.width)
138 managed_children--;
141 * Correct positioning of children.
144 cnt = 0;
145 while (managed_children)
147 child = parent->composite.children[cnt++];
149 if (!child->core.managed)
150 XtManageChild (child);
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;
157 managed_children--;
161 * Make sure all remaining children are unmanaged.
164 while (cnt < parent->composite.num_children)
166 child = parent->composite.children[cnt];
168 if (child->core.managed)
169 XtUnmanageChild (child);
171 if ((child->core.x != parent->core.width) ||
172 (child->core.y != parent->core.height))
173 XtMoveWidget (child, parent->core.width, parent->core.height);
175 cnt++;
180 static XtGeometryResult
181 PreferredSize (w, request, preferred)
182 lwMenuBarWidget w;
183 XtWidgetGeometry *request, *preferred;
185 Widget child;
186 int cnt;
189 * If no changes are being made to the width or height, just agree.
192 if (!(request->request_mode & CWWidth) &&
193 !(request->request_mode & CWHeight))
194 return (XtGeometryYes);
197 * Right now assume everything goes in one row. Calculate the
198 * minimum required width and height.
201 preferred->width = 0;
202 preferred->height = 0;
204 for (cnt = 0; cnt < w->composite.num_children; cnt++)
206 child = w->composite.children[cnt];
207 if (child->core.managed)
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;
218 preferred->request_mode = CWWidth | CWHeight;
221 * Case: both height and width requested
224 if ((request->request_mode & CWWidth) &&
225 (request->request_mode & CWHeight))
228 * Ok if same or bigger.
231 if (preferred->width <= request->width &&
232 preferred->height <= request->height)
234 preferred->width = request->width;
235 return (XtGeometryYes);
239 * If both dimensions are too small, say no.
242 else
243 if (preferred->width > request->width &&
244 preferred->height > request->height)
245 return (XtGeometryNo);
248 * Otherwise one must be right, so say almost.
251 else
252 return (XtGeometryAlmost);
256 * If only one dimension is requested, either its OK or it isn't.
259 else
261 if (request->request_mode & CWWidth)
263 if (preferred->width <= request->width)
265 preferred->width = request->width;
266 return (XtGeometryYes);
268 else
269 return (XtGeometryNo);
271 else if (request->request_mode & CWHeight)
273 if (preferred->height <= request->height)
275 return (XtGeometryYes);
277 else
278 return (XtGeometryNo);
281 return (XtGeometryYes);
286 static XtGeometryResult
287 GeometryManager (w, request, reply)
288 Widget w;
289 XtWidgetGeometry *request;
290 XtWidgetGeometry *reply;
293 lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent;
296 * If the widget wants to move, just say no.
299 if ((request->request_mode & CWX && request->x != w->core.x) ||
300 (request->request_mode & CWY && request->y != w->core.y))
301 return (XtGeometryNo);
304 * Since everything "fits" for now, grant all requests.
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;
314 do_layout (parent);
315 return (XtGeometryYes);
319 static XtGeometryResult
320 try_layout (parent)
321 lwMenuBarWidget parent;
323 Widget child;
324 int cnt;
325 int managed_children = 0;
326 int managed_width = 0;
327 int new_pos = 0;
330 * Determine number of children which will fit on one line.
331 * For now we ignore the rest, making sure they are unmanaged.
334 cnt = 0;
335 while ((cnt < (int) parent->composite.num_children) &&
336 (managed_width < (int) parent->core.width))
338 child = parent->composite.children[cnt++];
339 if (child->core.managed)
341 managed_children++;
342 managed_width += child->core.width + child->core.border_width * 2 +
343 HORIZ_SPACING;
347 if (managed_width > (int) parent->core.width)
348 return (XtGeometryNo);
349 else
350 return (XtGeometryYes);
355 static void
356 ChangeManaged (w)
357 lwMenuBarWidget w;
359 XtGeometryResult result;
361 result = try_layout (w);
363 if (result != XtGeometryYes)
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);
370 do_layout (w);