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)
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. */
22 #include "../src/lisp.h"
24 #include <X11/IntrinsicP.h>
25 #include <X11/Intrinsic.h>
26 #include <X11/CompositeP.h>
27 #include <X11/Composite.h>
28 #include "lwlib-Xol-mbP.h"
29 #include "lwlib-Xol-mb.h"
31 #define HORIZ_SPACING 4
32 #define VERT_SPACING 4
34 static void Initialize();
36 static void ChangeManaged();
37 static Boolean
SetValues();
38 static XtGeometryResult
GeometryManager();
39 static XtGeometryResult
PreferredSize();
40 static void do_layout();
41 static XtGeometryResult
try_layout();
43 lwMenuBarClassRec lwMenubarClassRec
=
46 /* core_class members */
48 (WidgetClass
) &compositeClassRec
, /* superclass */
49 "Menubar", /* class_name */
50 sizeof(lwMenuBarRec
), /* widget_size */
51 NULL
, /* class_initialize */
52 NULL
, /* class_part_initialize */
53 FALSE
, /* class_inited */
54 Initialize
, /* initialize */
55 NULL
, /* initialize_hook */
56 XtInheritRealize
, /* realize */
60 0, /* num_resources */
61 NULLQUARK
, /* xrm_class */
62 TRUE
, /* compress_motion */
63 XtExposeCompressMaximal
, /* compress_exposure */
64 TRUE
, /* compress_enterleave */
65 FALSE
, /* visible_interest */
69 NULL
, /* set_values */
70 NULL
, /* set_values_hook */
71 XtInheritSetValuesAlmost
, /* set_values_almost */
72 NULL
, /* get_values_hook */
73 NULL
, /* accept_focus */
74 XtVersion
, /* version */
75 NULL
, /* callback_private */
77 PreferredSize
, /* query_geometry */
78 NULL
, /* display_accelerator */
82 /* composite_class members */
84 GeometryManager
, /* geometry_manager */
85 ChangeManaged
, /* change_managed */
86 XtInheritInsertChild
, /* insert_child */
87 XtInheritDeleteChild
, /* delete_child */
91 /* Menubar class members */
96 WidgetClass lwMenubarWidgetClass
= (WidgetClass
) &lwMenubarClassRec
;
99 static void Initialize (request
, new)
100 lwMenuBarWidget request
, new;
102 if (request
->core
.width
<= 0)
104 if (request
->core
.height
<= 0)
105 new->core
.height
= 23;
117 lwMenuBarWidget parent
;
121 int managed_children
= 0;
122 int managed_width
= 0;
126 * Determine number of children which will fit on one line.
127 * For now we ignore the rest, making sure they are unmanaged.
131 while ((cnt
< (int) parent
->composite
.num_children
) &&
132 (managed_width
< (int) parent
->core
.width
))
134 child
= parent
->composite
.children
[cnt
++];
136 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
140 if (managed_width
> (int) parent
->core
.width
)
144 * Correct positioning of children.
148 while (managed_children
)
150 child
= parent
->composite
.children
[cnt
++];
152 if (!child
->core
.managed
)
153 XtManageChild (child
);
155 if ((child
->core
.x
!= new_pos
) || (child
->core
.y
!= 0))
156 XtMoveWidget (child
, new_pos
, 0);
157 new_pos
+= child
->core
.width
+ child
->core
.border_width
* 2 +
164 * Make sure all remaining children are unmanaged.
167 while (cnt
< parent
->composite
.num_children
)
169 child
= parent
->composite
.children
[cnt
];
171 if (child
->core
.managed
)
172 XtUnmanageChild (child
);
174 if ((child
->core
.x
!= parent
->core
.width
) ||
175 (child
->core
.y
!= parent
->core
.height
))
176 XtMoveWidget (child
, parent
->core
.width
, parent
->core
.height
);
183 static XtGeometryResult
184 PreferredSize (w
, request
, preferred
)
186 XtWidgetGeometry
*request
, *preferred
;
192 * If no changes are being made to the width or height, just agree.
195 if (!(request
->request_mode
& CWWidth
) &&
196 !(request
->request_mode
& CWHeight
))
197 return (XtGeometryYes
);
200 * Right now assume everything goes in one row. Calculate the
201 * minimum required width and height.
204 preferred
->width
= 0;
205 preferred
->height
= 0;
207 for (cnt
= 0; cnt
< w
->composite
.num_children
; cnt
++)
209 child
= w
->composite
.children
[cnt
];
210 if (child
->core
.managed
)
212 preferred
->width
+= child
->core
.width
+ child
->core
.border_width
*2 +
214 if (preferred
->height
< (Dimension
) (child
->core
.height
+
215 child
->core
.border_width
* 2))
216 preferred
->height
= child
->core
.height
+
217 child
->core
.border_width
* 2;
221 preferred
->request_mode
= CWWidth
| CWHeight
;
224 * Case: both height and width requested
227 if ((request
->request_mode
& CWWidth
) &&
228 (request
->request_mode
& CWHeight
))
231 * Ok if same or bigger.
234 if (preferred
->width
<= request
->width
&&
235 preferred
->height
<= request
->height
)
237 preferred
->width
= request
->width
;
238 return (XtGeometryYes
);
242 * If both dimensions are too small, say no.
246 if (preferred
->width
> request
->width
&&
247 preferred
->height
> request
->height
)
248 return (XtGeometryNo
);
251 * Otherwise one must be right, so say almost.
255 return (XtGeometryAlmost
);
259 * If only one dimension is requested, either its OK or it isn't.
264 if (request
->request_mode
& CWWidth
)
266 if (preferred
->width
<= request
->width
)
268 preferred
->width
= request
->width
;
269 return (XtGeometryYes
);
272 return (XtGeometryNo
);
274 else if (request
->request_mode
& CWHeight
)
276 if (preferred
->height
<= request
->height
)
278 return (XtGeometryYes
);
281 return (XtGeometryNo
);
284 return (XtGeometryYes
);
289 static XtGeometryResult
290 GeometryManager (w
, request
, reply
)
292 XtWidgetGeometry
*request
;
293 XtWidgetGeometry
*reply
;
296 lwMenuBarWidget parent
= (lwMenuBarWidget
) w
->core
.parent
;
299 * If the widget wants to move, just say no.
302 if ((request
->request_mode
& CWX
&& request
->x
!= w
->core
.x
) ||
303 (request
->request_mode
& CWY
&& request
->y
!= w
->core
.y
))
304 return (XtGeometryNo
);
307 * Since everything "fits" for now, grant all requests.
310 if (request
->request_mode
& CWWidth
)
311 w
->core
.width
= request
->width
;
312 if (request
->request_mode
& CWHeight
)
313 w
->core
.height
= request
->height
;
314 if (request
->request_mode
& CWBorderWidth
)
315 w
->core
.border_width
= request
->border_width
;
318 return (XtGeometryYes
);
322 static XtGeometryResult
324 lwMenuBarWidget parent
;
328 int managed_children
= 0;
329 int managed_width
= 0;
333 * Determine number of children which will fit on one line.
334 * For now we ignore the rest, making sure they are unmanaged.
338 while ((cnt
< (int) parent
->composite
.num_children
) &&
339 (managed_width
< (int) parent
->core
.width
))
341 child
= parent
->composite
.children
[cnt
++];
342 if (child
->core
.managed
)
345 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
350 if (managed_width
> (int) parent
->core
.width
)
351 return (XtGeometryNo
);
353 return (XtGeometryYes
);
362 XtGeometryResult result
;
364 result
= try_layout (w
);
366 if (result
!= XtGeometryYes
)
368 XtUnmanageChild (w
->composite
.children
[w
->composite
.num_children
- 1]);
369 XtMoveWidget (w
->composite
.children
[w
->composite
.num_children
-1],
370 w
->core
.width
, w
->core
.height
);