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. */
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();
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 */
57 0, /* num_resources */
58 NULLQUARK
, /* xrm_class */
59 TRUE
, /* compress_motion */
60 XtExposeCompressMaximal
, /* compress_exposure */
61 TRUE
, /* compress_enterleave */
62 FALSE
, /* visible_interest */
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 */
74 PreferredSize
, /* query_geometry */
75 NULL
, /* display_accelerator */
79 /* composite_class members */
81 GeometryManager
, /* geometry_manager */
82 ChangeManaged
, /* change_managed */
83 XtInheritInsertChild
, /* insert_child */
84 XtInheritDeleteChild
, /* delete_child */
88 /* Menubar class members */
93 WidgetClass lwMenubarWidgetClass
= (WidgetClass
) &lwMenubarClassRec
;
96 static void Initialize (request
, new)
97 lwMenuBarWidget request
, new;
99 if (request
->core
.width
<= 0)
101 if (request
->core
.height
<= 0)
102 new->core
.height
= 23;
114 lwMenuBarWidget parent
;
118 int managed_children
= 0;
119 int managed_width
= 0;
123 * Determine number of children which will fit on one line.
124 * For now we ignore the rest, making sure they are unmanaged.
128 while ((cnt
< (int) parent
->composite
.num_children
) &&
129 (managed_width
< (int) parent
->core
.width
))
131 child
= parent
->composite
.children
[cnt
++];
133 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
137 if (managed_width
> (int) parent
->core
.width
)
141 * Correct positioning of children.
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 +
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
);
180 static XtGeometryResult
181 PreferredSize (w
, request
, preferred
)
183 XtWidgetGeometry
*request
, *preferred
;
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 +
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.
243 if (preferred
->width
> request
->width
&&
244 preferred
->height
> request
->height
)
245 return (XtGeometryNo
);
248 * Otherwise one must be right, so say almost.
252 return (XtGeometryAlmost
);
256 * If only one dimension is requested, either its OK or it isn't.
261 if (request
->request_mode
& CWWidth
)
263 if (preferred
->width
<= request
->width
)
265 preferred
->width
= request
->width
;
266 return (XtGeometryYes
);
269 return (XtGeometryNo
);
271 else if (request
->request_mode
& CWHeight
)
273 if (preferred
->height
<= request
->height
)
275 return (XtGeometryYes
);
278 return (XtGeometryNo
);
281 return (XtGeometryYes
);
286 static XtGeometryResult
287 GeometryManager (w
, request
, reply
)
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
;
315 return (XtGeometryYes
);
319 static XtGeometryResult
321 lwMenuBarWidget parent
;
325 int managed_children
= 0;
326 int managed_width
= 0;
330 * Determine number of children which will fit on one line.
331 * For now we ignore the rest, making sure they are unmanaged.
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
)
342 managed_width
+= child
->core
.width
+ child
->core
.border_width
* 2 +
347 if (managed_width
> (int) parent
->core
.width
)
348 return (XtGeometryNo
);
350 return (XtGeometryYes
);
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
);