Mercurial > emacs
annotate lwlib/lwlib-Xolmb.c @ 42811:cf0c0ef57504
*** empty log message ***
| author | Jason Rumney <jasonr@gnu.org> |
|---|---|
| date | Thu, 17 Jan 2002 19:29:24 +0000 |
| parents | 7fb1caba0f51 |
| children |
| rev | line source |
|---|---|
| 5628 | 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 | |
|
14186
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
5628
diff
changeset
|
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
5628
diff
changeset
|
19 Boston, MA 02111-1307, USA. */ |
| 5628 | 20 |
| 41767 | 21 |
| 22 #include "../src/lisp.h" | |
| 23 | |
| 5628 | 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" | |
| 30 | |
| 31 #define HORIZ_SPACING 4 | |
| 32 #define VERT_SPACING 4 | |
| 33 | |
| 34 static void Initialize(); | |
| 35 static void Resize(); | |
| 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(); | |
| 42 | |
| 43 lwMenuBarClassRec lwMenubarClassRec = | |
| 44 { | |
| 45 { | |
| 46 /* core_class members */ | |
| 47 | |
| 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 */ | |
| 57 NULL, /* actions */ | |
| 58 0, /* num_actions */ | |
| 59 NULL, /* resources */ | |
| 60 0, /* num_resources */ | |
| 61 NULLQUARK, /* xrm_class */ | |
| 62 TRUE, /* compress_motion */ | |
| 63 XtExposeCompressMaximal, /* compress_exposure */ | |
| 64 TRUE, /* compress_enterleave */ | |
| 65 FALSE, /* visible_interest */ | |
| 66 NULL, /* destroy */ | |
| 67 Resize, /* resize */ | |
| 68 NULL, /* expose */ | |
| 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 */ | |
| 76 NULL, /* tm_table */ | |
| 77 PreferredSize, /* query_geometry */ | |
| 78 NULL, /* display_accelerator */ | |
| 79 NULL, /* extension */ | |
| 80 }, | |
| 81 { | |
| 82 /* composite_class members */ | |
| 83 | |
| 84 GeometryManager, /* geometry_manager */ | |
| 85 ChangeManaged, /* change_managed */ | |
| 86 XtInheritInsertChild, /* insert_child */ | |
| 87 XtInheritDeleteChild, /* delete_child */ | |
| 88 NULL, /* extension */ | |
| 89 }, | |
| 90 { | |
| 91 /* Menubar class members */ | |
| 92 | |
| 93 0, /* empty */ | |
| 94 } | |
| 95 }; | |
| 96 WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec; | |
| 97 | |
| 98 | |
| 99 static void Initialize (request, new) | |
| 100 lwMenuBarWidget request, new; | |
| 101 { | |
| 102 if (request->core.width <= 0) | |
| 103 new->core.width = 1; | |
| 104 if (request->core.height <= 0) | |
| 105 new->core.height = 23; | |
| 106 } | |
| 107 | |
| 108 static void | |
| 109 Resize (w) | |
| 110 lwMenuBarWidget w; | |
| 111 { | |
| 112 do_layout(w); | |
| 113 } | |
| 114 | |
| 115 static void | |
| 116 do_layout (parent) | |
| 117 lwMenuBarWidget parent; | |
| 118 { | |
| 119 Widget child; | |
| 120 int cnt; | |
| 121 int managed_children = 0; | |
| 122 int managed_width = 0; | |
| 123 int new_pos = 0; | |
| 124 | |
| 125 /* | |
| 126 * Determine number of children which will fit on one line. | |
| 127 * For now we ignore the rest, making sure they are unmanaged. | |
| 128 */ | |
| 129 | |
| 130 cnt = 0; | |
| 131 while ((cnt < (int) parent->composite.num_children) && | |
| 132 (managed_width < (int) parent->core.width)) | |
| 133 { | |
| 134 child = parent->composite.children[cnt++]; | |
| 135 managed_children++; | |
| 136 managed_width += child->core.width + child->core.border_width * 2 + | |
| 137 HORIZ_SPACING; | |
| 138 } | |
| 139 | |
| 140 if (managed_width > (int) parent->core.width) | |
| 141 managed_children--; | |
| 142 | |
| 143 /* | |
| 144 * Correct positioning of children. | |
| 145 */ | |
| 146 | |
| 147 cnt = 0; | |
| 148 while (managed_children) | |
| 149 { | |
| 150 child = parent->composite.children[cnt++]; | |
| 151 | |
| 152 if (!child->core.managed) | |
| 153 XtManageChild (child); | |
| 154 | |
| 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 + | |
| 158 HORIZ_SPACING; | |
| 159 | |
| 160 managed_children--; | |
| 161 } | |
| 162 | |
| 163 /* | |
| 164 * Make sure all remaining children are unmanaged. | |
| 165 */ | |
| 166 | |
| 167 while (cnt < parent->composite.num_children) | |
| 168 { | |
| 169 child = parent->composite.children[cnt]; | |
| 170 | |
| 171 if (child->core.managed) | |
| 172 XtUnmanageChild (child); | |
| 173 | |
| 174 if ((child->core.x != parent->core.width) || | |
| 175 (child->core.y != parent->core.height)) | |
| 176 XtMoveWidget (child, parent->core.width, parent->core.height); | |
| 177 | |
| 178 cnt++; | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 | |
| 183 static XtGeometryResult | |
| 184 PreferredSize (w, request, preferred) | |
| 185 lwMenuBarWidget w; | |
| 186 XtWidgetGeometry *request, *preferred; | |
| 187 { | |
| 188 Widget child; | |
| 189 int cnt; | |
| 190 | |
| 191 /* | |
| 192 * If no changes are being made to the width or height, just agree. | |
| 193 */ | |
| 194 | |
| 195 if (!(request->request_mode & CWWidth) && | |
| 196 !(request->request_mode & CWHeight)) | |
| 197 return (XtGeometryYes); | |
| 198 | |
| 199 /* | |
| 200 * Right now assume everything goes in one row. Calculate the | |
| 201 * minimum required width and height. | |
| 202 */ | |
| 203 | |
| 204 preferred->width = 0; | |
| 205 preferred->height = 0; | |
| 206 | |
| 207 for (cnt = 0; cnt < w->composite.num_children; cnt++) | |
| 208 { | |
| 209 child = w->composite.children[cnt]; | |
| 210 if (child->core.managed) | |
| 211 { | |
| 212 preferred->width += child->core.width + child->core.border_width*2 + | |
| 213 HORIZ_SPACING; | |
| 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; | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 preferred->request_mode = CWWidth | CWHeight; | |
| 222 | |
| 223 /* | |
| 224 * Case: both height and width requested | |
| 225 */ | |
| 226 | |
| 227 if ((request->request_mode & CWWidth) && | |
| 228 (request->request_mode & CWHeight)) | |
| 229 { | |
| 230 /* | |
| 231 * Ok if same or bigger. | |
| 232 */ | |
| 233 | |
| 234 if (preferred->width <= request->width && | |
| 235 preferred->height <= request->height) | |
| 236 { | |
| 237 preferred->width = request->width; | |
| 238 return (XtGeometryYes); | |
| 239 } | |
| 240 | |
| 241 /* | |
| 242 * If both dimensions are too small, say no. | |
| 243 */ | |
| 244 | |
| 245 else | |
| 246 if (preferred->width > request->width && | |
| 247 preferred->height > request->height) | |
| 248 return (XtGeometryNo); | |
| 249 | |
| 250 /* | |
| 251 * Otherwise one must be right, so say almost. | |
| 252 */ | |
| 253 | |
| 254 else | |
| 255 return (XtGeometryAlmost); | |
| 256 } | |
| 257 | |
| 258 /* | |
| 259 * If only one dimension is requested, either its OK or it isn't. | |
| 260 */ | |
| 261 | |
| 262 else | |
| 263 { | |
| 264 if (request->request_mode & CWWidth) | |
| 265 { | |
| 266 if (preferred->width <= request->width) | |
| 267 { | |
| 268 preferred->width = request->width; | |
| 269 return (XtGeometryYes); | |
| 270 } | |
| 271 else | |
| 272 return (XtGeometryNo); | |
| 273 } | |
| 274 else if (request->request_mode & CWHeight) | |
| 275 { | |
| 276 if (preferred->height <= request->height) | |
| 277 { | |
| 278 return (XtGeometryYes); | |
| 279 } | |
| 280 else | |
| 281 return (XtGeometryNo); | |
| 282 } | |
| 283 | |
| 284 return (XtGeometryYes); | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 | |
| 289 static XtGeometryResult | |
| 290 GeometryManager (w, request, reply) | |
| 291 Widget w; | |
| 292 XtWidgetGeometry *request; | |
| 293 XtWidgetGeometry *reply; | |
| 294 { | |
| 295 | |
| 296 lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent; | |
| 297 | |
| 298 /* | |
| 299 * If the widget wants to move, just say no. | |
| 300 */ | |
| 301 | |
| 302 if ((request->request_mode & CWX && request->x != w->core.x) || | |
| 303 (request->request_mode & CWY && request->y != w->core.y)) | |
| 304 return (XtGeometryNo); | |
| 305 | |
| 306 /* | |
| 307 * Since everything "fits" for now, grant all requests. | |
| 308 */ | |
| 309 | |
| 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; | |
| 316 | |
| 317 do_layout (parent); | |
| 318 return (XtGeometryYes); | |
| 319 } | |
| 320 | |
| 321 | |
| 322 static XtGeometryResult | |
| 323 try_layout (parent) | |
| 324 lwMenuBarWidget parent; | |
| 325 { | |
| 326 Widget child; | |
| 327 int cnt; | |
| 328 int managed_children = 0; | |
| 329 int managed_width = 0; | |
| 330 int new_pos = 0; | |
| 331 | |
| 332 /* | |
| 333 * Determine number of children which will fit on one line. | |
| 334 * For now we ignore the rest, making sure they are unmanaged. | |
| 335 */ | |
| 336 | |
| 337 cnt = 0; | |
| 338 while ((cnt < (int) parent->composite.num_children) && | |
| 339 (managed_width < (int) parent->core.width)) | |
| 340 { | |
| 341 child = parent->composite.children[cnt++]; | |
| 342 if (child->core.managed) | |
| 343 { | |
| 344 managed_children++; | |
| 345 managed_width += child->core.width + child->core.border_width * 2 + | |
| 346 HORIZ_SPACING; | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 if (managed_width > (int) parent->core.width) | |
| 351 return (XtGeometryNo); | |
| 352 else | |
| 353 return (XtGeometryYes); | |
| 354 } | |
| 355 | |
| 356 | |
| 357 | |
| 358 static void | |
| 359 ChangeManaged (w) | |
| 360 lwMenuBarWidget w; | |
| 361 { | |
| 362 XtGeometryResult result; | |
| 363 | |
| 364 result = try_layout (w); | |
| 365 | |
| 366 if (result != XtGeometryYes) | |
| 367 { | |
| 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); | |
| 371 } | |
| 372 | |
| 373 do_layout (w); | |
| 374 } |
