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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #include <X11/IntrinsicP.h>
21 #include <X11/Intrinsic.h>
22 #include <X11/CompositeP.h>
23 #include <X11/Composite.h>
24 #include "lwlib-Xol-mbP.h"
25 #include "lwlib-Xol-mb.h"
27 #define HORIZ_SPACING 4
28 #define VERT_SPACING 4
30 static void Initialize();
32 static void ChangeManaged();
33 static Boolean
SetValues();
34 static XtGeometryResult
GeometryManager();
35 static XtGeometryResult
PreferredSize();
36 static void do_layout();
37 static XtGeometryResult
try_layout();
39 lwMenuBarClassRec lwMenubarClassRec
=
42 /* core_class members */
44 (WidgetClass
) &compositeClassRec
, /* superclass */
45 "Menubar", /* class_name */
46 sizeof(lwMenuBarRec
), /* widget_size */
47 NULL
, /* class_initialize */
48 NULL
, /* class_part_initialize */
49 FALSE
, /* class_inited */
50 Initialize
, /* initialize */
51 NULL
, /* initialize_hook */
52 XtInheritRealize
, /* realize */
56 0, /* num_resources */
57 NULLQUARK
, /* xrm_class */
58 TRUE
, /* compress_motion */
59 XtExposeCompressMaximal
, /* compress_exposure */
60 TRUE
, /* compress_enterleave */
61 FALSE
, /* visible_interest */
65 NULL
, /* set_values */
66 NULL
, /* set_values_hook */
67 XtInheritSetValuesAlmost
, /* set_values_almost */
68 NULL
, /* get_values_hook */
69 NULL
, /* accept_focus */
70 XtVersion
, /* version */
71 NULL
, /* callback_private */
73 PreferredSize
, /* query_geometry */
74 NULL
, /* display_accelerator */
78 /* composite_class members */
80 GeometryManager
, /* geometry_manager */
81 ChangeManaged
, /* change_managed */
82 XtInheritInsertChild
, /* insert_child */
83 XtInheritDeleteChild
, /* delete_child */
87 /* Menubar class members */
92 WidgetClass lwMenubarWidgetClass
= (WidgetClass
) &lwMenubarClassRec
;
95 static void Initialize (request
, new)
96 lwMenuBarWidget request
, new;
98 if (request
->core
.width
<= 0)
100 if (request
->core
.height
<= 0)
101 new->core
.height
= 23;
113 lwMenuBarWidget parent
;
117 int managed_children
= 0;
118 int managed_width
= 0;
122 * Determine number of children which will fit on one line.
123 * For now we ignore the rest, making sure they are unmanaged.
127 while ((cnt
< (int) parent
->composite
.num_children
) &&
128 (managed_width
< (int) parent
->core
.width
))
130 child
= parent
->composite
.children
[cnt
++];
132 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
136 if (managed_width
> (int) parent
->core
.width
)
140 * Correct positioning of children.
144 while (managed_children
)
146 child
= parent
->composite
.children
[cnt
++];
148 if (!child
->core
.managed
)
149 XtManageChild (child
);
151 if ((child
->core
.x
!= new_pos
) || (child
->core
.y
!= 0))
152 XtMoveWidget (child
, new_pos
, 0);
153 new_pos
+= child
->core
.width
+ child
->core
.border_width
* 2 +
160 * Make sure all remaining children are unmanaged.
163 while (cnt
< parent
->composite
.num_children
)
165 child
= parent
->composite
.children
[cnt
];
167 if (child
->core
.managed
)
168 XtUnmanageChild (child
);
170 if ((child
->core
.x
!= parent
->core
.width
) ||
171 (child
->core
.y
!= parent
->core
.height
))
172 XtMoveWidget (child
, parent
->core
.width
, parent
->core
.height
);
179 static XtGeometryResult
180 PreferredSize (w
, request
, preferred
)
182 XtWidgetGeometry
*request
, *preferred
;
188 * If no changes are being made to the width or height, just agree.
191 if (!(request
->request_mode
& CWWidth
) &&
192 !(request
->request_mode
& CWHeight
))
193 return (XtGeometryYes
);
196 * Right now assume everything goes in one row. Calculate the
197 * minimum required width and height.
200 preferred
->width
= 0;
201 preferred
->height
= 0;
203 for (cnt
= 0; cnt
< w
->composite
.num_children
; cnt
++)
205 child
= w
->composite
.children
[cnt
];
206 if (child
->core
.managed
)
208 preferred
->width
+= child
->core
.width
+ child
->core
.border_width
*2 +
210 if (preferred
->height
< (Dimension
) (child
->core
.height
+
211 child
->core
.border_width
* 2))
212 preferred
->height
= child
->core
.height
+
213 child
->core
.border_width
* 2;
217 preferred
->request_mode
= CWWidth
| CWHeight
;
220 * Case: both height and width requested
223 if ((request
->request_mode
& CWWidth
) &&
224 (request
->request_mode
& CWHeight
))
227 * Ok if same or bigger.
230 if (preferred
->width
<= request
->width
&&
231 preferred
->height
<= request
->height
)
233 preferred
->width
= request
->width
;
234 return (XtGeometryYes
);
238 * If both dimensions are too small, say no.
242 if (preferred
->width
> request
->width
&&
243 preferred
->height
> request
->height
)
244 return (XtGeometryNo
);
247 * Otherwise one must be right, so say almost.
251 return (XtGeometryAlmost
);
255 * If only one dimension is requested, either its OK or it isn't.
260 if (request
->request_mode
& CWWidth
)
262 if (preferred
->width
<= request
->width
)
264 preferred
->width
= request
->width
;
265 return (XtGeometryYes
);
268 return (XtGeometryNo
);
270 else if (request
->request_mode
& CWHeight
)
272 if (preferred
->height
<= request
->height
)
274 return (XtGeometryYes
);
277 return (XtGeometryNo
);
280 return (XtGeometryYes
);
285 static XtGeometryResult
286 GeometryManager (w
, request
, reply
)
288 XtWidgetGeometry
*request
;
289 XtWidgetGeometry
*reply
;
292 lwMenuBarWidget parent
= (lwMenuBarWidget
) w
->core
.parent
;
295 * If the widget wants to move, just say no.
298 if ((request
->request_mode
& CWX
&& request
->x
!= w
->core
.x
) ||
299 (request
->request_mode
& CWY
&& request
->y
!= w
->core
.y
))
300 return (XtGeometryNo
);
303 * Since everything "fits" for now, grant all requests.
306 if (request
->request_mode
& CWWidth
)
307 w
->core
.width
= request
->width
;
308 if (request
->request_mode
& CWHeight
)
309 w
->core
.height
= request
->height
;
310 if (request
->request_mode
& CWBorderWidth
)
311 w
->core
.border_width
= request
->border_width
;
314 return (XtGeometryYes
);
318 static XtGeometryResult
320 lwMenuBarWidget parent
;
324 int managed_children
= 0;
325 int managed_width
= 0;
329 * Determine number of children which will fit on one line.
330 * For now we ignore the rest, making sure they are unmanaged.
334 while ((cnt
< (int) parent
->composite
.num_children
) &&
335 (managed_width
< (int) parent
->core
.width
))
337 child
= parent
->composite
.children
[cnt
++];
338 if (child
->core
.managed
)
341 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
346 if (managed_width
> (int) parent
->core
.width
)
347 return (XtGeometryNo
);
349 return (XtGeometryYes
);
358 XtGeometryResult result
;
360 result
= try_layout (w
);
362 if (result
!= XtGeometryYes
)
364 XtUnmanageChild (w
->composite
.children
[w
->composite
.num_children
- 1]);
365 XtMoveWidget (w
->composite
.children
[w
->composite
.num_children
-1],
366 w
->core
.width
, w
->core
.height
);