Mercurial > hg > xemacs-beta
annotate src/glyphs-widget.c @ 5533:11da5b828d10
shell-command and shell-command-on-region API compliant with FSF 23.3.1
| author | Mats Lidell <mats.lidell@cag.se> |
|---|---|
| date | Sun, 31 Jul 2011 01:29:09 +0200 |
| parents | 4dee0387b9de |
| children | 56144c8593a8 |
| rev | line source |
|---|---|
| 428 | 1 /* Widget-specific glyph objects. |
| 863 | 2 Copyright (C) 1998, 1999, 2000, 2002 Andy Piper. |
| 1318 | 3 Copyright (C) 2003 Ben Wing. |
| 428 | 4 |
| 5 This file is part of XEmacs. | |
| 6 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5176
diff
changeset
|
7 XEmacs is free software: you can redistribute it and/or modify it |
| 428 | 8 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5176
diff
changeset
|
9 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5176
diff
changeset
|
10 option) any later version. |
| 428 | 11 |
| 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
| 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 15 for more details. | |
| 16 | |
| 17 You should have received a copy of the GNU General Public License | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5176
diff
changeset
|
18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 19 |
| 20 /* Synched up with: Not in FSF. */ | |
| 21 | |
| 22 /* written by Andy Piper <andy@xemacs.org> */ | |
| 23 | |
| 24 #include <config.h> | |
| 25 #include "lisp.h" | |
| 800 | 26 |
| 27 #include "bytecode.h" | |
| 428 | 28 #include "console.h" |
| 872 | 29 #include "device-impl.h" |
| 428 | 30 #include "faces.h" |
| 800 | 31 #include "frame.h" |
| 428 | 32 #include "glyphs.h" |
| 800 | 33 #include "gui.h" |
| 34 #include "insdel.h" | |
| 35 #include "lstream.h" | |
|
5176
8b2f75cecb89
rename objects* (.c, .h and .el files) to fontcolor*
Ben Wing <ben@xemacs.org>
parents:
5047
diff
changeset
|
36 #include "fontcolor.h" |
| 800 | 37 #include "opaque.h" |
| 428 | 38 #include "window.h" |
| 39 | |
| 40 DEFINE_IMAGE_INSTANTIATOR_FORMAT (button); | |
| 41 DEFINE_IMAGE_INSTANTIATOR_FORMAT (combo_box); | |
| 42 Lisp_Object Qcombo_box; | |
| 43 DEFINE_IMAGE_INSTANTIATOR_FORMAT (edit_field); | |
| 44 Lisp_Object Qedit_field; | |
| 45 DEFINE_IMAGE_INSTANTIATOR_FORMAT (scrollbar); | |
| 46 Lisp_Object Qscrollbar; | |
| 47 DEFINE_IMAGE_INSTANTIATOR_FORMAT (widget); | |
| 48 DEFINE_IMAGE_INSTANTIATOR_FORMAT (label); | |
| 49 Lisp_Object Qlabel; | |
| 50 DEFINE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge); | |
| 51 Lisp_Object Qprogress_gauge; | |
| 52 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tree_view); | |
| 53 Lisp_Object Qtree_view; | |
| 54 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control); | |
| 55 Lisp_Object Qtab_control; | |
| 56 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout); | |
| 57 Lisp_Object Qlayout; | |
| 442 | 58 DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout); |
| 59 Lisp_Object Qnative_layout; | |
| 428 | 60 |
| 61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; | |
| 442 | 62 Lisp_Object Qmake_glyph; |
| 863 | 63 Lisp_Object Vwidget_border_width; |
| 64 | |
| 65 static int widget_border_width (Lisp_Object domain); | |
| 66 static int widget_spacing (Lisp_Object domain); | |
| 67 static void widget_query_string_geometry (Lisp_Object string, Lisp_Object face, | |
| 68 int *width, int *height, Lisp_Object domain); | |
| 428 | 69 |
| 1068 | 70 #define BORDER_FIDDLE_FACTOR 10 |
| 428 | 71 #ifdef DEBUG_WIDGETS |
| 72 int debug_widget_instances; | |
| 73 #endif | |
| 74 | |
| 75 /* TODO: | |
| 438 | 76 - tooltips for controls, especially buttons. |
| 440 | 77 - keyboard traversal. |
| 78 - lisp configurable layout. | |
| 428 | 79 */ |
| 80 | |
| 438 | 81 /* In MS-Windows normal windows work in pixels, dialog boxes work in |
| 428 | 82 dialog box units. Why? sigh. We could reuse the metrics for dialogs |
| 83 if this were not the case. As it is we have to position things | |
| 84 pixel wise. I'm not even sure that X has this problem at least for | |
| 85 buttons in groups. */ | |
| 86 static int | |
| 87 widget_possible_dest_types (void) | |
| 88 { | |
| 89 return IMAGE_WIDGET_MASK; | |
| 90 } | |
| 91 | |
| 92 static void | |
| 442 | 93 check_valid_instantiator (Lisp_Object data) |
| 428 | 94 { |
| 95 Lisp_Object glyph = data; | |
| 96 if (SYMBOLP (data)) | |
| 97 glyph = XSYMBOL (data)->value; | |
| 98 | |
| 442 | 99 if (!CONSP (glyph) && !VECTORP (glyph)) |
| 100 invalid_argument ("instantiator item must be a vector", data); | |
| 428 | 101 } |
| 102 | |
| 103 static void | |
| 104 check_valid_orientation (Lisp_Object data) | |
| 105 { | |
| 106 if (!EQ (data, Qhorizontal) | |
| 107 && | |
| 108 !EQ (data, Qvertical)) | |
| 563 | 109 invalid_constant ("unknown orientation for layout", data); |
| 428 | 110 } |
| 111 | |
| 112 static void | |
| 438 | 113 check_valid_tab_orientation (Lisp_Object data) |
| 114 { | |
| 115 if (!EQ (data, Qtop) | |
| 116 && | |
| 117 !EQ (data, Qbottom) | |
| 118 && | |
| 119 !EQ (data, Qleft) | |
| 120 && | |
| 121 !EQ (data, Qright)) | |
| 563 | 122 invalid_constant ("unknown orientation for tab control", data); |
| 438 | 123 } |
| 124 | |
| 125 static void | |
| 428 | 126 check_valid_justification (Lisp_Object data) |
| 127 { | |
| 863 | 128 if (!EQ (data, Qleft) |
| 129 && | |
| 130 !EQ (data, Qright) | |
| 131 && | |
| 132 !EQ (data, Qtop) | |
| 133 && | |
| 134 !EQ (data, Qbottom) | |
| 135 && | |
| 136 !EQ (data, Qcenter)) | |
| 563 | 137 invalid_constant ("unknown justification for layout", data); |
| 428 | 138 } |
| 139 | |
| 140 static void | |
| 141 check_valid_border (Lisp_Object data) | |
| 142 { | |
| 143 if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out) | |
| 144 && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out) | |
| 145 && !GLYPHP (data) && !VECTORP (data)) | |
| 442 | 146 invalid_argument ("unknown border style for layout", data); |
| 428 | 147 } |
| 148 | |
| 149 static void | |
| 2286 | 150 check_valid_anything (Lisp_Object UNUSED (data)) |
| 428 | 151 { |
| 152 } | |
| 153 | |
| 154 static void | |
| 155 check_valid_callback (Lisp_Object data) | |
| 156 { | |
| 157 if (!SYMBOLP (data) | |
| 158 && !COMPILED_FUNCTIONP (data) | |
| 159 && !CONSP (data)) | |
| 160 { | |
| 442 | 161 invalid_argument (":callback must be a function or expression", data); |
| 428 | 162 } |
| 163 } | |
| 164 | |
| 165 static void | |
| 442 | 166 check_valid_int_or_function (Lisp_Object data) |
| 167 { | |
| 458 | 168 if (!INTP (data) && !CONSP (data) && !SYMBOLP (data)) |
| 442 | 169 invalid_argument ("must be an integer or expresssion", data); |
| 170 } | |
| 171 | |
| 172 static void | |
| 428 | 173 check_valid_symbol (Lisp_Object data) |
| 174 { | |
| 175 CHECK_SYMBOL (data); | |
| 176 } | |
| 177 | |
| 178 static void | |
| 179 check_valid_string_or_vector (Lisp_Object data) | |
| 180 { | |
| 181 if (!STRINGP (data) && !VECTORP (data)) | |
| 442 | 182 invalid_argument (":descriptor must be a string or a vector", data); |
| 428 | 183 } |
| 184 | |
| 793 | 185 static void |
| 442 | 186 check_valid_item_list (Lisp_Object items) |
| 428 | 187 { |
| 2367 | 188 EXTERNAL_LIST_LOOP_2 (elt, items) |
| 428 | 189 { |
| 2367 | 190 if (STRINGP (elt)) |
| 191 CHECK_STRING (elt); | |
| 192 else if (VECTORP (elt)) | |
| 193 gui_parse_item_keywords (elt); | |
| 194 else if (LISTP (elt)) | |
| 195 check_valid_item_list (elt); | |
| 428 | 196 else |
| 2367 | 197 invalid_argument ("Item must be vector, list or string", elt); |
| 428 | 198 } |
| 199 } | |
| 200 | |
| 201 static void | |
| 442 | 202 check_valid_instantiator_list (Lisp_Object data) |
| 428 | 203 { |
| 2367 | 204 EXTERNAL_LIST_LOOP_2 (elt, data) |
| 428 | 205 { |
| 2367 | 206 check_valid_instantiator (elt); |
| 428 | 207 } |
| 208 } | |
| 209 | |
| 210 static Lisp_Object | |
| 211 glyph_instantiator_to_glyph (Lisp_Object sym) | |
| 212 { | |
| 213 /* This function calls lisp. */ | |
| 214 Lisp_Object glyph = sym; | |
| 215 struct gcpro gcpro1; | |
| 442 | 216 |
| 428 | 217 GCPRO1 (glyph); |
| 218 /* if we have a symbol get at the actual data */ | |
| 219 if (SYMBOLP (glyph)) | |
| 220 glyph = XSYMBOL (glyph)->value; | |
| 442 | 221 |
| 428 | 222 if (CONSP (glyph)) |
|
4677
8f1ee2d15784
Support full Common Lisp multiple values in C.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3466
diff
changeset
|
223 glyph = IGNORE_MULTIPLE_VALUES (Feval (glyph)); |
| 428 | 224 |
| 225 /* Be really helpful to the user. */ | |
| 226 if (VECTORP (glyph)) | |
| 227 { | |
| 442 | 228 glyph = call1 (Qmake_glyph, glyph); |
| 428 | 229 } |
| 230 | |
| 231 /* substitute the new glyph */ | |
| 232 RETURN_UNGCPRO (glyph); | |
| 233 } | |
| 234 | |
| 442 | 235 static void |
| 428 | 236 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val) |
| 237 { | |
| 238 int i; | |
| 239 /* substitute the new glyph */ | |
| 240 for (i = 0; i < XVECTOR_LENGTH (inst); i++) | |
| 241 { | |
| 242 if (EQ (key, XVECTOR_DATA (inst)[i])) | |
| 243 { | |
| 244 XVECTOR_DATA (inst)[i+1] = val; | |
| 245 break; | |
| 246 } | |
| 247 } | |
| 248 } | |
| 249 | |
| 863 | 250 /* Determine the border with of the widget. */ |
| 251 static int | |
| 252 widget_border_width (Lisp_Object domain) | |
| 253 { | |
| 254 /* #### FIXME -- need to use specifiers (Vwidget_border_width) for | |
| 255 some portion of this. */ | |
| 256 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), | |
| 257 widget_border_width)) | |
| 258 return DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ()); | |
| 259 else | |
| 260 return DEFAULT_WIDGET_BORDER_WIDTH; | |
| 261 } | |
| 262 | |
| 263 static int | |
| 264 widget_instance_border_width (Lisp_Image_Instance* ii) | |
| 265 { | |
| 266 return widget_border_width (IMAGE_INSTANCE_DOMAIN (ii)); | |
| 267 } | |
| 268 | |
| 2297 | 269 /* #### It's not clear to me what the value of logical_unit_height should |
| 270 be, or whether it should even depend on the current image_instance. It | |
| 271 really should probably only depend on the default widget face and the | |
| 272 domain, however you can envisage users wanting different logical units | |
| 273 for nested layouts - so using the properties of the current layout is | |
| 274 probably not so dumb. */ | |
| 863 | 275 static int |
| 276 logical_unit_height (Lisp_Object text, Lisp_Object face, Lisp_Object domain) | |
| 277 { | |
| 278 int charheight = 0; | |
| 279 widget_query_string_geometry (text, face, | |
| 280 0, &charheight, domain); | |
| 281 /* For the returned value to be useful it needs to be big enough to | |
|
5384
3889ef128488
Fix misspelled words, and some grammar, across the entire source tree.
Jerry James <james@xemacs.org>
parents:
5176
diff
changeset
|
282 accommodate the largest single-height widget. This is currently |
| 863 | 283 the edit-field. */ |
| 284 return charheight + 2 * widget_spacing (domain) | |
| 285 + 4 * widget_border_width (domain); | |
| 286 } | |
| 287 | |
| 288 static int | |
| 289 widget_logical_unit_height (Lisp_Image_Instance* ii) | |
| 290 { | |
| 291 return logical_unit_height (NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)) ? | |
| 866 | 292 NILP (IMAGE_INSTANCE_NAME (ii)) ? |
| 293 Fsymbol_name (Qwidget) | |
| 294 : IMAGE_INSTANCE_NAME (ii) | |
| 863 | 295 : IMAGE_INSTANCE_WIDGET_TEXT (ii), |
| 296 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 297 IMAGE_INSTANCE_DOMAIN (ii)); | |
| 298 } | |
| 299 | |
| 438 | 300 /* Wire widget property invocations to specific widgets. The problem |
| 301 we are solving here is that when instantiators get converted to | |
| 302 instances they lose some type information (they just become | |
| 303 subwindows or widgets for example). For widgets we need to preserve | |
| 304 this type information so that we can do widget specific operations | |
| 305 on the instances. This is encoded in the widget type | |
| 306 field. widget_property gets invoked by decoding the primary type | |
| 307 (Qwidget), <widget>_property then invokes based on the secondary | |
| 308 type (Qedit_field for example). It is debatable whether we should | |
| 309 wire things in this generalised way rather than treating widgets | |
| 310 specially in image_instance_property. */ | |
| 442 | 311 static Lisp_Object |
| 428 | 312 widget_property (Lisp_Object image_instance, Lisp_Object prop) |
| 313 { | |
| 440 | 314 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); |
| 428 | 315 struct image_instantiator_methods* meths; |
| 442 | 316 #if 0 /* The usefulness of this is dubious. */ |
| 428 | 317 /* first see if its a general property ... */ |
| 318 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop))) | |
| 319 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil); | |
| 442 | 320 #endif |
| 428 | 321 /* .. then try device specific methods ... */ |
| 442 | 322 meths = decode_device_ii_format (image_instance_device (image_instance), |
| 323 IMAGE_INSTANCE_WIDGET_TYPE (ii), | |
| 428 | 324 ERROR_ME_NOT); |
| 325 if (meths && HAS_IIFORMAT_METH_P (meths, property)) | |
| 326 return IIFORMAT_METH (meths, property, (image_instance, prop)); | |
| 327 /* ... then format specific methods ... */ | |
| 442 | 328 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), |
| 428 | 329 ERROR_ME_NOT); |
| 330 if (meths && HAS_IIFORMAT_METH_P (meths, property)) | |
| 331 return IIFORMAT_METH (meths, property, (image_instance, prop)); | |
| 332 /* ... then fail */ | |
| 333 return Qunbound; | |
| 334 } | |
| 335 | |
| 442 | 336 /* Update the displayed properties of a widget. |
| 337 | |
| 338 #### This has been adapted from the original set_property functions | |
| 339 and thus reuses the state management of that. A better solution is | |
| 340 to simply re-parse the instantiator when items need updating. This | |
| 341 make comparing differences much simpler and obviates the need for a | |
| 342 lot of the state variables. | |
| 343 | |
| 344 #### property is still a valid function since we have to be able to | |
| 345 extract information from the actual widget. | |
| 346 | |
| 3094 | 347 #### widget_update should probably be re-written to use the |
| 442 | 348 instantiator. We probably want to keep a record of the differences |
| 349 also to make this easy. We would also need a pending_instantiator | |
| 350 so that changes could be delayed. */ | |
| 351 static void | |
| 352 widget_update (Lisp_Object image_instance, Lisp_Object instantiator) | |
| 428 | 353 { |
| 440 | 354 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); |
| 428 | 355 struct image_instantiator_methods* meths; |
| 454 | 356 struct gcpro gcpro1; |
| 428 | 357 |
| 442 | 358 Lisp_Object text = find_keyword_in_vector (instantiator, Q_text); |
| 454 | 359 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); |
| 360 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); | |
| 361 Lisp_Object descriptor_item = Qnil; | |
| 362 | |
| 363 GCPRO1 (descriptor_item); | |
| 364 | |
| 442 | 365 /* Pick up any generic properties that we might need to keep hold |
| 454 | 366 of. |
| 367 #### This is potentially bogus because it is changing the items | |
| 368 in place rather than in the pending items. */ | |
| 442 | 369 if (!NILP (text)) |
| 438 | 370 { |
| 442 | 371 IMAGE_INSTANCE_WIDGET_TEXT (ii) = text; |
| 372 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1; | |
| 438 | 373 } |
| 374 | |
| 454 | 375 /* Retrieve the gui item information. This is easy if we have been |
| 376 provided with a vector, more difficult if we have just been given | |
| 377 keywords. | |
| 378 | |
| 379 #### This is inconsistent with instantiation in that you have to | |
| 380 have the :descriptor keyword for updates in order to recognise | |
| 381 changes. */ | |
| 382 if (VECTORP (desc)) | |
| 383 { | |
| 384 descriptor_item = gui_parse_item_keywords_no_errors (desc); | |
| 385 } | |
| 386 else | |
| 387 { | |
| 388 /* Since we are updating the instantiator could be incomplete | |
| 389 and hence the gui item descriptor not well formed. We | |
| 390 therefore try updating and discard the results if nothing | |
| 391 changed. */ | |
| 392 descriptor_item = copy_gui_item (IMAGE_INSTANCE_WIDGET_ITEM (ii)); | |
| 393 if (!update_gui_item_keywords (descriptor_item, instantiator)) | |
| 394 descriptor_item = Qnil; | |
| 395 } | |
| 396 | |
| 397 /* Record new items for update. *_redisplay will do the | |
| 398 rest. */ | |
| 399 if (!EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout) | |
| 400 && | |
| 401 !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout)) | |
| 402 { | |
| 403 if (!NILP (items)) | |
| 404 { | |
| 405 if (NILP (descriptor_item)) | |
| 406 descriptor_item = IMAGE_INSTANCE_WIDGET_ITEM (ii); | |
| 407 | |
| 408 check_valid_item_list (items); | |
| 409 #ifdef DEBUG_WIDGET_OUTPUT | |
| 410 stderr_out ("items for widget %p updated\n", | |
| 411 IMAGE_INSTANCE_SUBWINDOW_ID (ii)); | |
| 412 #endif | |
| 413 /* Don't set the actual items since we might decide not to use | |
| 414 the new ones (because nothing has really changed). If we did | |
| 415 set them and didn't use them then we would get into whole | |
| 416 heaps of trouble when the old items get GC'd. */ | |
| 417 descriptor_item = Fcons (descriptor_item, parse_gui_item_tree_children (items)); | |
| 418 } | |
| 419 /* If the descriptor was updated but not the items we need to fill | |
| 420 in the `new' items. */ | |
| 421 else if (!NILP (descriptor_item) | |
| 422 && | |
| 423 CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
| 424 { | |
| 425 descriptor_item = Fcons | |
| 426 (descriptor_item, | |
| 427 copy_gui_item_tree (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 if (!NILP (descriptor_item)) | |
| 432 { | |
| 433 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = descriptor_item; | |
| 434 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1; | |
| 435 } | |
| 436 | |
| 437 UNGCPRO; | |
| 438 | |
| 438 | 439 /* Now try device specific methods first ... */ |
| 442 | 440 meths = decode_device_ii_format (image_instance_device (image_instance), |
| 441 IMAGE_INSTANCE_WIDGET_TYPE (ii), | |
| 442 ERROR_ME_NOT); | |
| 443 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator)); | |
| 444 /* ... then format specific methods ... */ | |
| 445 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), | |
| 446 ERROR_ME_NOT); | |
| 447 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator)); | |
| 448 #if 0 /* The usefulness of this is dubious. */ | |
| 449 /* we didn't do any device specific properties, so shove the property in our plist. */ | |
| 450 IMAGE_INSTANCE_WIDGET_PROPS (ii) | |
| 451 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val); | |
| 452 #endif | |
| 453 } | |
| 454 | |
| 455 /* Like the rest of redisplay, we want widget updates to occur | |
| 456 asynchronously. Thus toolkit specific methods for setting | |
| 457 properties must be called by redisplay instead of by *_update. Thus | |
| 458 *_update records the change and this function actually implements | |
| 459 it. We want to be slightly clever about this however by supplying | |
| 460 format specific functions for the updates instead of lumping them | |
| 461 all into this function. Note that there is no need for format | |
| 462 generic functions. This is not the same as widget_update! */ | |
| 463 void | |
| 464 redisplay_widget (Lisp_Object widget) | |
| 465 { | |
| 466 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget); | |
| 467 struct image_instantiator_methods* meths; | |
| 468 | |
| 469 if (!WIDGET_IMAGE_INSTANCEP (widget) | |
| 470 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout) | |
| 471 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout)) | |
| 472 return; | |
| 473 | |
| 474 /* Device-format specific methods - e.g. x_tab_control_redisplay () */ | |
| 475 meths = decode_device_ii_format (image_instance_device (widget), | |
| 428 | 476 IMAGE_INSTANCE_WIDGET_TYPE (ii), |
| 477 ERROR_ME_NOT); | |
| 442 | 478 MAYBE_IIFORMAT_METH (meths, redisplay, (widget)); |
| 479 | |
| 480 /* Device generic methods - e.g. x_redisplay_widget (). We must | |
| 481 update the widget's size as it may have been changed by the the | |
| 482 layout routines. We also do this here so that explicit resizing | |
| 483 from lisp does not result in synchronous updates. Do this last so | |
| 484 that format-specific methods have an opportunity to prevent | |
| 485 wholesale changes - e.g. rebuilding tabs. */ | |
| 863 | 486 MAYBE_DEVMETH (DOMAIN_XDEVICE (IMAGE_INSTANCE_DOMAIN (ii)), |
| 487 redisplay_widget, (ii)); | |
| 442 | 488 |
| 489 /* Pick up the items we recorded earlier. */ | |
| 490 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) | |
| 428 | 491 { |
| 442 | 492 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = |
| 493 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii); | |
| 494 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; | |
| 428 | 495 } |
| 496 } | |
| 497 | |
| 771 | 498 static void |
| 499 widget_query_string_geometry (Lisp_Object string, Lisp_Object face, | |
| 500 int *width, int *height, Lisp_Object domain) | |
| 501 { | |
| 502 struct device *d = DOMAIN_XDEVICE (domain); | |
| 503 | |
| 504 if (HAS_DEVMETH_P (d, widget_query_string_geometry)) | |
| 505 DEVMETH (d, widget_query_string_geometry, | |
| 506 (string, face, width, height, domain)); | |
| 507 else | |
| 508 query_string_geometry (string, face, width, height, 0, domain); | |
| 509 | |
| 510 } | |
| 511 | |
| 863 | 512 /* Determine the spacing of the widget. */ |
| 513 static int | |
| 514 widget_spacing (Lisp_Object domain) | |
| 515 { | |
| 516 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_spacing)) | |
| 517 return DEVMETH (DOMAIN_XDEVICE (domain), | |
| 518 widget_spacing, (0)); | |
| 519 else | |
| 520 return DEFAULT_WIDGET_SPACING; | |
| 521 } | |
| 522 | |
| 438 | 523 /* Query for a widgets desired geometry. If no type specific method is |
| 524 provided then use the widget text to calculate sizes. */ | |
| 442 | 525 static void |
| 526 widget_query_geometry (Lisp_Object image_instance, | |
| 527 int* width, int* height, | |
| 438 | 528 enum image_instance_geometry disp, Lisp_Object domain) |
| 529 { | |
| 440 | 530 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); |
| 438 | 531 struct image_instantiator_methods* meths; |
| 442 | 532 Lisp_Object dynamic_width = Qnil; |
| 533 Lisp_Object dynamic_height = Qnil; | |
| 438 | 534 |
| 535 /* First just set up what we already have. */ | |
| 536 if (width) *width = IMAGE_INSTANCE_WIDTH (ii); | |
| 537 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii); | |
| 442 | 538 |
| 438 | 539 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) |
| 540 || | |
| 541 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) | |
| 542 { | |
| 543 /* .. then try device specific methods ... */ | |
| 442 | 544 meths = decode_device_ii_format (image_instance_device (image_instance), |
| 545 IMAGE_INSTANCE_WIDGET_TYPE (ii), | |
| 438 | 546 ERROR_ME_NOT); |
| 547 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) | |
| 442 | 548 IIFORMAT_METH (meths, query_geometry, (image_instance, |
| 438 | 549 width, height, disp, |
| 550 domain)); | |
| 551 else | |
| 552 { | |
| 553 /* ... then format specific methods ... */ | |
| 442 | 554 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), |
| 438 | 555 ERROR_ME_NOT); |
| 556 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) | |
| 442 | 557 IIFORMAT_METH (meths, query_geometry, (image_instance, |
| 438 | 558 width, height, disp, |
| 559 domain)); | |
| 442 | 560 else |
| 438 | 561 { |
| 442 | 562 int w, h; |
| 563 | |
| 438 | 564 /* Then if we are allowed to resize the widget, make the |
| 565 size the same as the text dimensions. */ | |
| 771 | 566 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), |
| 567 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 568 &w, &h, domain); | |
| 438 | 569 /* Adjust the size for borders. */ |
| 3466 | 570 if (width && IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) |
| 863 | 571 *width = w + 2 * widget_instance_border_width (ii); |
| 3466 | 572 if (height && IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) |
| 863 | 573 *height = h + 2 * widget_instance_border_width (ii); |
| 438 | 574 } |
| 575 } | |
| 442 | 576 /* Finish off with dynamic sizing. */ |
| 3466 | 577 if (width && !NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii))) |
| 442 | 578 { |
| 853 | 579 dynamic_width = |
| 580 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)); | |
| 442 | 581 if (INTP (dynamic_width)) |
| 582 *width = XINT (dynamic_width); | |
| 583 } | |
| 3466 | 584 if (height && !NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) |
| 442 | 585 { |
| 853 | 586 dynamic_height = |
| 587 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)); | |
| 442 | 588 if (INTP (dynamic_height)) |
| 589 *height = XINT (dynamic_height); | |
| 590 } | |
| 438 | 591 } |
| 592 } | |
| 593 | |
| 442 | 594 static int |
| 595 widget_layout (Lisp_Object image_instance, | |
| 596 int width, int height, int xoffset, int yoffset, | |
| 597 Lisp_Object domain) | |
| 438 | 598 { |
| 440 | 599 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); |
| 438 | 600 struct image_instantiator_methods* meths; |
| 601 | |
| 602 /* .. then try device specific methods ... */ | |
| 442 | 603 meths = decode_device_ii_format (image_instance_device (image_instance), |
| 604 IMAGE_INSTANCE_WIDGET_TYPE (ii), | |
| 438 | 605 ERROR_ME_NOT); |
| 606 if (meths && HAS_IIFORMAT_METH_P (meths, layout)) | |
| 442 | 607 return IIFORMAT_METH (meths, layout, (image_instance, |
| 608 width, height, xoffset, yoffset, | |
| 609 domain)); | |
| 438 | 610 else |
| 611 { | |
| 612 /* ... then format specific methods ... */ | |
| 442 | 613 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), |
| 438 | 614 ERROR_ME_NOT); |
| 615 if (meths && HAS_IIFORMAT_METH_P (meths, layout)) | |
| 442 | 616 return IIFORMAT_METH (meths, layout, (image_instance, |
| 617 width, height, xoffset, yoffset, | |
| 618 domain)); | |
| 438 | 619 } |
| 442 | 620 return 1; |
| 438 | 621 } |
| 622 | |
| 428 | 623 static void |
| 624 widget_validate (Lisp_Object instantiator) | |
| 625 { | |
| 626 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); | |
| 627 | |
| 628 if (NILP (desc)) | |
| 563 | 629 invalid_argument ("Must supply :descriptor", instantiator); |
| 428 | 630 |
| 631 if (VECTORP (desc)) | |
| 632 gui_parse_item_keywords (desc); | |
| 633 | |
| 634 if (!NILP (find_keyword_in_vector (instantiator, Q_width)) | |
| 635 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width))) | |
| 563 | 636 invalid_argument ("Must supply only one of :width and :pixel-width", instantiator); |
| 428 | 637 |
| 638 if (!NILP (find_keyword_in_vector (instantiator, Q_height)) | |
| 639 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height))) | |
| 563 | 640 invalid_argument ("Must supply only one of :height and :pixel-height", instantiator); |
| 428 | 641 } |
| 642 | |
| 643 static void | |
| 644 combo_box_validate (Lisp_Object instantiator) | |
| 645 { | |
| 646 widget_validate (instantiator); | |
| 442 | 647 if (NILP (find_keyword_in_vector (instantiator, Q_items))) |
| 563 | 648 invalid_argument ("Must supply item list", instantiator); |
| 428 | 649 } |
| 650 | |
| 651 /* we need to convert things like glyphs to images, eval expressions | |
| 652 etc.*/ | |
| 653 static Lisp_Object | |
| 2286 | 654 widget_normalize (Lisp_Object inst, Lisp_Object UNUSED (console_type), |
| 655 Lisp_Object UNUSED (dest_mask)) | |
| 428 | 656 { |
| 657 /* This function can call lisp */ | |
| 658 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image); | |
| 659 | |
| 660 /* we need to eval glyph if its an expression, we do this for the | |
| 442 | 661 same reasons we normalize file to data. |
| 662 | |
| 663 #### should just normalize the data. */ | |
| 428 | 664 if (!NILP (glyph)) |
| 665 { | |
| 1318 | 666 substitute_keyword_value (inst, Q_image, |
| 667 glyph_instantiator_to_glyph (glyph)); | |
| 428 | 668 } |
| 669 | |
| 670 return inst; | |
| 671 } | |
| 672 | |
| 673 static void | |
| 440 | 674 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type) |
| 428 | 675 { |
| 676 /* initialize_subwindow_image_instance (ii);*/ | |
| 677 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type; | |
| 678 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; | |
| 438 | 679 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil); |
| 428 | 680 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); |
| 442 | 681 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil; |
| 682 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; | |
| 683 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil; | |
| 684 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil; | |
| 438 | 685 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; |
| 686 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; | |
| 442 | 687 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL; |
| 863 | 688 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = 0; |
| 689 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = 0; | |
| 428 | 690 } |
| 691 | |
| 692 /* Instantiate a button widget. Unfortunately instantiated widgets are | |
| 693 particular to a frame since they need to have a parent. It's not | |
| 694 like images where you just select the image into the context you | |
| 695 want to display it in and BitBlt it. So image instances can have a | |
| 696 many-to-one relationship with things you see, whereas widgets can | |
| 697 only be one-to-one (i.e. per frame) */ | |
| 698 void | |
| 438 | 699 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
| 700 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 701 int dest_mask, Lisp_Object domain) | |
| 428 | 702 { |
| 442 | 703 /* #### practically all of this should be moved to widget_update() |
| 704 so that users can dynamically change all possible widget | |
| 705 properties. */ | |
| 440 | 706 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
| 428 | 707 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face); |
| 708 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height); | |
| 709 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width); | |
| 710 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width); | |
| 711 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height); | |
| 712 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); | |
| 713 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); | |
| 440 | 714 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); |
| 438 | 715 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); |
| 442 | 716 Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width); |
| 717 Lisp_Object ifocus = find_keyword_in_vector (instantiator, Q_initial_focus); | |
| 428 | 718 int pw=0, ph=0, tw=0, th=0; |
| 442 | 719 |
| 428 | 720 /* this just does pixel type sizing */ |
| 721 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, | |
| 722 dest_mask, domain); | |
| 723 | |
| 442 | 724 if (!(dest_mask & IMAGE_WIDGET_MASK)) |
| 725 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK); | |
| 428 | 726 |
| 727 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]); | |
| 728 | |
| 440 | 729 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET; |
| 730 | |
| 428 | 731 /* retrieve the fg and bg colors */ |
| 732 if (!NILP (face)) | |
| 438 | 733 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face)); |
| 428 | 734 |
| 454 | 735 /* Retrieve the gui item information. This is easy if we have been |
| 428 | 736 provided with a vector, more difficult if we have just been given |
| 454 | 737 keywords. Note that standard gui descriptor shortcuts will not work |
| 738 because of keyword parsing. | |
| 739 | |
| 740 #### This is bogus in that descriptor and items share the same slot, | |
| 741 we should rationalize. */ | |
| 742 if (VECTORP (desc)) | |
| 743 { | |
| 744 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = | |
| 745 gui_parse_item_keywords_no_errors (desc); | |
| 746 } | |
| 747 else | |
| 428 | 748 { |
| 749 /* big cheat - we rely on the fact that a gui item looks like an instantiator */ | |
| 442 | 750 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = |
| 454 | 751 widget_gui_parse_item_keywords (instantiator); |
| 428 | 752 } |
| 753 | |
| 440 | 754 /* Pick up the orientation before we do our first layout. */ |
| 755 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical)) | |
| 442 | 756 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL; |
| 440 | 757 |
| 428 | 758 /* parse more gui items out of the properties */ |
| 442 | 759 if (!NILP (items) && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout) |
| 760 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout)) | |
| 428 | 761 { |
| 442 | 762 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = |
| 763 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), | |
| 764 parse_gui_item_tree_children (items)); | |
| 428 | 765 } |
| 766 | |
| 438 | 767 /* Normalize size information. We now only assign sizes if the user |
| 768 gives us some explicitly, or there are some constraints that we | |
| 769 can't change later on. Otherwise we postpone sizing until query | |
| 770 geometry gets called. */ | |
| 771 if (!NILP (pixwidth)) /* pixwidth takes precendent */ | |
| 772 { | |
| 442 | 773 if (!INTP (pixwidth)) |
| 774 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth; | |
| 775 else | |
| 776 { | |
| 777 pw = XINT (pixwidth); | |
| 778 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; | |
| 779 } | |
| 438 | 780 } |
| 781 else if (!NILP (width)) | |
| 782 { | |
| 783 tw = XINT (width); | |
| 784 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; | |
| 785 } | |
| 786 | |
| 428 | 787 if (!NILP (pixheight)) |
| 438 | 788 { |
| 442 | 789 if (!INTP (pixheight)) |
| 790 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight; | |
| 791 else | |
| 792 { | |
| 793 ph = XINT (pixheight); | |
| 794 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; | |
| 795 } | |
| 438 | 796 } |
| 797 else if (!NILP (height) && XINT (height) > 1) | |
| 798 { | |
| 799 th = XINT (height); | |
| 800 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; | |
| 801 } | |
| 802 | |
| 803 /* Taking the default face information when the user has specified | |
| 804 size in characters is probably as good as any since the widget | |
| 805 face is more likely to be proportional and thus give inadequate | |
| 806 results. Using character sizes can only ever be approximate | |
| 863 | 807 anyway. :height is measured in logical characters which take into |
| 808 account the borders and spacing on widgets. */ | |
| 809 if (tw) | |
| 810 { | |
| 811 int charwidth; | |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
4677
diff
changeset
|
812 default_face_font_info (domain, 0, 0, &charwidth, 0, 0); |
| 863 | 813 pw = ROUND_UP (charwidth * tw + 4 * widget_instance_border_width (ii), charwidth); |
| 814 } | |
| 815 | |
| 816 /* For heights the widget face is more appropriate. */ | |
| 817 if (th == 1) | |
| 438 | 818 { |
| 863 | 819 int charheight; |
| 820 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) | |
| 821 { | |
| 822 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), | |
| 823 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 824 0, &charheight, domain); | |
| 825 } | |
| 826 else | |
| 827 { | |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
4677
diff
changeset
|
828 default_face_font_info (domain, 0, 0, 0, &charheight, 0); |
| 863 | 829 } |
| 830 ph = (charheight + 2 * widget_instance_border_width (ii)) * th; | |
| 831 } | |
| 832 /* For heights > 1 use logical units. */ | |
| 833 else if (th > 1) | |
| 834 { | |
| 835 ph = widget_logical_unit_height (ii) * th; | |
| 438 | 836 } |
| 428 | 837 |
| 838 /* for a widget with an image pick up the dimensions from that */ | |
| 839 if (!NILP (glyph)) | |
| 840 { | |
| 438 | 841 if (!pw) |
| 863 | 842 pw = glyph_width (glyph, image_instance) + 2 * widget_instance_border_width (ii); |
| 438 | 843 if (!ph) |
| 863 | 844 ph = glyph_height (glyph, image_instance) + 2 * widget_instance_border_width (ii); |
| 438 | 845 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; |
| 846 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; | |
| 428 | 847 } |
| 848 | |
| 442 | 849 /* Pick up the margin width. */ |
| 850 if (!NILP (mwidth)) | |
| 851 IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth); | |
| 852 | |
| 853 IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (ii) = !NILP (ifocus); | |
| 438 | 854 |
| 442 | 855 /* Layout for the layout widget is premature at this point since the |
| 856 children will not have been instantiated. We can't instantiate | |
| 857 them until the device instantiation method for the layout has | |
| 858 been executed. We do however want to record any specified | |
| 859 dimensions. */ | |
| 860 if (pw) IMAGE_INSTANCE_WIDTH (ii) = pw; | |
| 861 if (ph) IMAGE_INSTANCE_HEIGHT (ii) = ph; | |
| 862 } | |
| 863 | |
| 864 static void | |
| 2286 | 865 widget_post_instantiate (Lisp_Object UNUSED (image_instance), |
| 866 #ifdef DEBUG_WIDGETS | |
| 867 Lisp_Object instantiator, | |
| 868 #else | |
| 869 Lisp_Object UNUSED (instantiator), | |
| 870 #endif | |
| 871 Lisp_Object UNUSED (domain)) | |
| 442 | 872 { |
| 428 | 873 #ifdef DEBUG_WIDGETS |
| 874 debug_widget_instances++; | |
| 875 stderr_out ("instantiated "); | |
| 876 debug_print (instantiator); | |
| 877 stderr_out ("%d widgets instantiated\n", debug_widget_instances); | |
| 878 #endif | |
| 879 } | |
| 880 | |
| 442 | 881 /* Get the geometry of a button control. We need to adjust the size |
| 882 depending on the type of button. */ | |
| 883 static void | |
| 884 button_query_geometry (Lisp_Object image_instance, | |
| 885 int* width, int* height, | |
| 2286 | 886 enum image_instance_geometry UNUSED (disp), |
| 887 Lisp_Object domain) | |
| 442 | 888 { |
| 889 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 890 int w, h; | |
| 771 | 891 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), |
| 892 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 893 &w, &h, domain); | |
| 442 | 894 /* Adjust the size for borders. */ |
| 895 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) | |
| 896 { | |
| 863 | 897 *width = w + 3 * widget_instance_border_width (ii); |
| 442 | 898 |
| 899 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio) | |
| 900 || | |
| 901 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle)) | |
| 902 /* This is an approximation to the size of the actual button bit. */ | |
| 903 *width += 12; | |
| 904 } | |
| 905 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) | |
| 863 | 906 *height = h + 3 * widget_instance_border_width (ii); |
| 907 } | |
| 908 | |
| 909 /* Get the geometry of an edit field. */ | |
| 910 static void | |
| 911 edit_field_query_geometry (Lisp_Object image_instance, | |
| 2286 | 912 int* width, int* height, |
| 913 enum image_instance_geometry UNUSED (disp), | |
| 914 Lisp_Object domain) | |
| 863 | 915 { |
| 916 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 917 int w, h; | |
| 918 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), | |
| 919 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 920 &w, &h, domain); | |
| 921 /* Adjust the size for borders. */ | |
| 922 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) | |
| 923 *width = w + 4 * widget_instance_border_width (ii); | |
| 924 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) | |
| 925 *height = h + 4 * widget_instance_border_width (ii); | |
| 442 | 926 } |
| 927 | |
| 438 | 928 /* tree-view geometry - get the height right */ |
| 428 | 929 static void |
| 442 | 930 tree_view_query_geometry (Lisp_Object image_instance, |
| 931 int* width, int* height, | |
| 2286 | 932 enum image_instance_geometry UNUSED (disp), |
| 933 Lisp_Object domain) | |
| 428 | 934 { |
| 440 | 935 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
| 438 | 936 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); |
| 937 | |
| 442 | 938 |
| 438 | 939 if (*width) |
| 940 { | |
| 941 /* #### what should this be. reconsider when X has tree views. */ | |
| 771 | 942 widget_query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), |
| 943 IMAGE_INSTANCE_WIDGET_FACE (ii), | |
| 944 width, 0, domain); | |
| 438 | 945 } |
| 946 if (*height) | |
| 947 { | |
| 948 int len, h; | |
| 863 | 949 /* #### widget face would be better here. */ |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
4677
diff
changeset
|
950 default_face_font_info (domain, 0, 0, 0, &h, 0); |
| 438 | 951 GET_LIST_LENGTH (items, len); |
| 952 *height = len * h; | |
| 953 } | |
| 428 | 954 } |
| 955 | |
| 2297 | 956 /* Get the geometry of a tab control. This is based on the number of |
| 957 items and text therein in the tab control. */ | |
| 428 | 958 static void |
| 442 | 959 tab_control_query_geometry (Lisp_Object image_instance, |
| 960 int* width, int* height, | |
| 2286 | 961 enum image_instance_geometry UNUSED (disp), |
| 962 Lisp_Object domain) | |
| 428 | 963 { |
| 440 | 964 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
| 442 | 965 Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); |
| 428 | 966 Lisp_Object rest; |
| 442 | 967 int tw = 0, th = 0; |
| 428 | 968 |
| 438 | 969 LIST_LOOP (rest, items) |
| 428 | 970 { |
| 442 | 971 int h, w; |
| 438 | 972 |
| 2297 | 973 /* #### Maybe we should allow items to be a list of strings? |
| 974 Ie, autoconvert "label" -> ["label" "label" :selected maybe-t]. | |
| 975 Maybe there's a better place (or several places) to do this? | |
| 976 If so, change image_instantiator_tab_control back to use | |
| 977 check_valid_item_list for checking Q_items. -- sjt */ | |
| 771 | 978 widget_query_string_geometry (XGUI_ITEM (XCAR (rest))->name, |
| 863 | 979 IMAGE_INSTANCE_WIDGET_FACE (ii), |
| 980 &w, &h, domain); | |
| 981 tw += 5 * widget_instance_border_width (ii); /* some bias */ | |
| 438 | 982 tw += w; |
| 863 | 983 th = max (th, h + 2 * widget_instance_border_width (ii)); |
| 428 | 984 } |
| 985 | |
| 438 | 986 /* Fixup returned values depending on orientation. */ |
| 987 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)) | |
| 988 { | |
| 989 if (height) *height = tw; | |
| 990 if (width) *width = th; | |
| 991 } | |
| 992 else | |
| 993 { | |
| 994 if (height) *height = th; | |
| 995 if (width) *width = tw; | |
| 996 } | |
| 428 | 997 } |
| 998 | |
| 442 | 999 /* Determine whether only the order has changed for a tab. */ |
| 1318 | 1000 int |
| 1001 tab_control_order_only_changed (Lisp_Object image_instance) | |
| 442 | 1002 { |
| 1318 | 1003 /* Called within redisplay */ |
| 442 | 1004 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
| 1005 int found = 0, len, pending_len; | |
| 1006 Lisp_Object rest; | |
| 1007 | |
| 1008 /* Degenerate case. */ | |
| 1009 if (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) | |
| 1010 return 1; | |
| 1011 | |
| 1012 /* See whether we just need a change in order. */ | |
| 1013 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_ITEMS (ii), len); | |
| 1014 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), | |
| 1015 pending_len); | |
| 1016 if (len == pending_len) | |
| 1017 { | |
| 1018 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) | |
| 1019 { | |
| 1020 Lisp_Object pending_rest; | |
| 1021 found = 0; | |
| 1022 LIST_LOOP (pending_rest, | |
| 1023 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) | |
| 1024 { | |
| 1025 if (gui_item_equal_sans_selected (XCAR (rest), | |
| 1913 | 1026 XCAR (pending_rest), 0)) |
| 442 | 1027 { |
| 1028 found = 1; | |
| 1029 break; | |
| 1030 } | |
| 1031 } | |
| 1032 if (!found) | |
| 1033 break; | |
| 1034 } | |
| 1035 } | |
| 1036 return found; | |
| 1037 } | |
| 1038 | |
| 428 | 1039 |
| 1040 /***************************************************************************** | |
| 1041 * widget layout * | |
| 1042 *****************************************************************************/ | |
| 442 | 1043 /* We need to cascade normalization.*/ |
| 428 | 1044 static Lisp_Object |
| 442 | 1045 layout_normalize (Lisp_Object inst, Lisp_Object console_type, |
| 1046 Lisp_Object dest_mask) | |
| 428 | 1047 { |
| 1048 /* This function can call lisp */ | |
| 442 | 1049 struct gcpro gcpro1, gcpro2; |
| 1050 Lisp_Object alist = Qnil, new_items = Qnil, border; | |
| 1051 /* This function can call lisp */ | |
| 1052 Lisp_Object items; | |
| 1053 | |
| 1054 GCPRO2 (alist, new_items); | |
| 1055 alist = tagged_vector_to_alist (inst); | |
| 1056 items = assq_no_quit (Q_items, alist); | |
| 1057 | |
| 1058 /* We need to normalize sub-objects. */ | |
| 428 | 1059 if (!NILP (items)) |
| 1060 { | |
| 1061 Lisp_Object rest; | |
| 442 | 1062 LIST_LOOP (rest, XCDR (items)) |
| 428 | 1063 { |
| 442 | 1064 /* Substitute the new instantiator */ |
| 1065 new_items = Fcons (normalize_image_instantiator (XCAR (rest), | |
| 1066 console_type, dest_mask), | |
| 1067 new_items); | |
| 1068 } | |
| 1069 new_items = Fnreverse (new_items); | |
| 1070 Fsetcdr (items, new_items); | |
| 1071 } | |
| 1072 /* Normalize the border spec. */ | |
| 1073 border = assq_no_quit (Q_border, alist); | |
| 1074 if (!NILP (border) && VECTORP (XCDR (border))) | |
| 1075 { | |
| 1076 Fsetcdr (border, normalize_image_instantiator (XCDR (border), | |
| 1077 console_type, dest_mask)); | |
| 1078 } | |
| 1079 | |
| 1080 { | |
| 1081 Lisp_Object result = alist_to_tagged_vector (XVECTOR_DATA (inst)[0], | |
| 1082 alist); | |
| 1083 free_alist (alist); | |
| 1084 RETURN_UNGCPRO (result); | |
| 1085 } | |
| 1086 } | |
| 1087 | |
| 1088 /* Update the instances in the layout. */ | |
| 1089 static void | |
| 1090 layout_update (Lisp_Object image_instance, Lisp_Object instantiator) | |
| 1091 { | |
| 1092 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1093 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); | |
| 1094 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border); | |
| 863 | 1095 Lisp_Object justify = find_keyword_in_vector (instantiator, Q_justify); |
| 1096 Lisp_Object hjustify = find_keyword_in_vector (instantiator, Q_horizontally_justify); | |
| 1097 Lisp_Object vjustify = find_keyword_in_vector (instantiator, Q_vertically_justify); | |
| 442 | 1098 Lisp_Object border = Qnil; |
| 1099 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); | |
| 1100 int structure_changed = 0; | |
| 1101 struct gcpro gcpro1; | |
| 1102 | |
| 863 | 1103 /* Pick up horizontal justification, left is the default.*/ |
| 1104 if (!NILP (hjustify)) | |
| 1105 { | |
| 1106 if (EQ (hjustify, Qright) || EQ (hjustify, Qbottom)) | |
| 1107 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT; | |
| 1108 else if (EQ (hjustify, Qcenter)) | |
| 1109 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; | |
| 1110 } | |
| 1111 /* If not set use general justification. */ | |
| 1112 else if (!NILP (justify)) | |
| 1113 { | |
| 1114 if (EQ (justify, Qright) || EQ (justify, Qbottom)) | |
| 1115 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT; | |
| 1116 else if (EQ (justify, Qcenter)) | |
| 1117 IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; | |
| 1118 } | |
| 1119 | |
| 1120 /* Pick up vertical justification, top is the default. */ | |
| 1121 if (!NILP (vjustify)) | |
| 1122 { | |
| 1123 if (EQ (vjustify, Qright) || EQ (vjustify, Qbottom)) | |
| 1124 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM; | |
| 1125 else if (EQ (vjustify, Qcenter)) | |
| 1126 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; | |
| 1127 } | |
| 1128 /* If not set use general justification. */ | |
| 1129 else if (!NILP (justify)) | |
| 1130 { | |
| 1131 if (EQ (justify, Qright) || EQ (justify, Qbottom)) | |
| 1132 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM; | |
| 1133 else if (EQ (justify, Qcenter)) | |
| 1134 IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; | |
| 1135 } | |
| 1136 | |
| 442 | 1137 /* We want to avoid consing if we can. This is quite awkward because |
| 1138 we have to deal with the border as well as the items. */ | |
| 1139 GCPRO1 (border); | |
| 1140 | |
| 1141 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) | |
| 1142 { | |
| 1143 border = XCAR (children); | |
| 1144 children = XCDR (children); | |
| 1145 } | |
| 1146 | |
| 1147 #ifdef DEBUG_WIDGET_OUTPUT | |
| 1148 stderr_out ("layout updated\n"); | |
| 1149 #endif | |
| 1150 /* Update the border. */ | |
| 1151 if (!NILP (border_inst)) | |
| 1152 { | |
| 1153 if (VECTORP (border_inst)) | |
| 1154 { | |
| 1155 /* We are going to be sneaky here and add the border text as | |
| 1156 just another child, the layout and output routines don't know | |
| 1157 this and will just display at the offsets we prescribe. */ | |
| 1158 if (!NILP (border)) | |
| 1159 call3 (Qset_glyph_image, border, border_inst, | |
| 1160 IMAGE_INSTANCE_DOMAIN (ii)); | |
| 1161 else | |
| 1162 { | |
| 1163 border = Fcons (call1 (Qmake_glyph, border_inst), Qnil); | |
| 1164 structure_changed = 1; | |
| 1165 } | |
| 1166 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0); | |
| 1167 } | |
| 1168 else | |
| 1169 { | |
| 1170 if (!NILP (border)) | |
| 1171 { | |
| 1172 border = Qnil; | |
| 1173 structure_changed = 1; | |
| 1174 } | |
| 1175 if (EQ (border_inst, Qt)) | |
| 1176 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in; | |
| 1177 else | |
| 1178 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border_inst; | |
| 428 | 1179 } |
| 1180 } | |
| 442 | 1181 |
| 1182 /* Pick up the sub-widgets. */ | |
| 1183 if (!NILP (items)) | |
| 428 | 1184 { |
| 442 | 1185 int len1, len2; |
| 1186 GET_LIST_LENGTH (items, len1); | |
| 1187 GET_LIST_LENGTH (children, len2); | |
| 1188 /* The structure hasn't changed so just update the images. */ | |
| 1189 if (!structure_changed && len1 == len2) | |
| 1190 { | |
| 1191 /* Pick up the sub-widgets. */ | |
| 1192 for (; !NILP (children); children = XCDR (children), items = XCDR (items)) | |
| 1193 { | |
| 1194 call3 (Qset_glyph_image, XCAR (children), XCAR (items), | |
| 1195 IMAGE_INSTANCE_DOMAIN (ii)); | |
| 1196 } | |
| 1197 } | |
| 1198 /* The structure has changed so start over. */ | |
| 1199 else | |
| 1200 { | |
| 1201 /* Instantiate any new glyphs. */ | |
| 1202 for (; !NILP (items); items = XCDR (items)) | |
| 1203 { | |
| 458 | 1204 /* #### We really want to use call_with_suspended_errors |
| 1205 here, but it won't allow us to call lisp. */ | |
| 442 | 1206 border = Fcons (call1 (Qmake_glyph, XCAR (items)), border); |
| 1207 } | |
| 1208 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Fnreverse (border); | |
| 1209 } | |
| 428 | 1210 } |
| 442 | 1211 UNGCPRO; |
| 1212 } | |
| 1213 | |
| 1214 static void | |
| 1215 layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
| 1216 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | |
| 1217 int dest_mask, Lisp_Object domain) | |
| 1218 { | |
| 1219 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1220 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); | |
| 1221 | |
| 1222 #ifdef DEBUG_WIDGET_OUTPUT | |
| 1223 stderr_out ("layout instantiated\n"); | |
| 1224 #endif | |
| 1225 /* Do widget type instantiation first. */ | |
| 1226 widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, | |
| 1227 dest_mask, domain); | |
| 1228 | |
| 1229 if (NILP (orient)) | |
| 1230 { | |
| 1231 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL; | |
| 1232 } | |
| 1233 | |
| 1234 /* Get child glyphs and finish instantiation. We can't do image | |
| 1235 instance children yet as we might not have a containing | |
| 1236 window. */ | |
| 1237 layout_update (image_instance, instantiator); | |
| 1238 } | |
| 1239 | |
| 1240 static void | |
| 2286 | 1241 layout_post_instantiate (Lisp_Object UNUSED (image_instance), |
| 1242 Lisp_Object UNUSED (instantiator), | |
| 1243 Lisp_Object UNUSED (domain)) | |
| 442 | 1244 { |
| 428 | 1245 } |
| 1246 | |
| 440 | 1247 /* Layout widget. Sizing commentary: we have a number of problems that |
| 1248 we would like to address. Some consider some of these more | |
| 1249 important than others. It used to be that size information was | |
| 1250 determined at instantiation time and was then fixed forever | |
| 434 | 1251 after. Generally this is not what we want. Users want size to be |
| 1252 "big enough" to accommodate whatever they are trying to show and | |
| 1253 this is dependent on text length, lines, font metrics etc. Of | |
| 1254 course these attributes can change dynamically and so the size | |
| 1255 should changed dynamically also. Only in a few limited cases should | |
| 1256 the size be fixed and remain fixed. Of course this actually means | |
| 442 | 1257 that we don't really want to specify the size *at all* for most |
| 434 | 1258 widgets - we want it to be discovered dynamically. Thus we can |
| 1259 envisage the following scenarios: | |
| 442 | 1260 |
| 434 | 1261 1. A button is sized to accommodate its text, the text changes and the |
| 442 | 1262 button should change size also. |
| 434 | 1263 |
| 1264 2. A button is given an explicit size. Its size should never change. | |
| 1265 | |
| 1266 3. Layout is put inside an area. The size of the area changes, the | |
| 442 | 1267 layout should change with it. |
| 434 | 1268 |
| 1269 4. A button grows to accommodate additional text. The whitespace | |
| 1270 around it should be modified to cope with the new layout | |
| 442 | 1271 requirements. |
| 434 | 1272 |
| 1273 5. A button grows. The area surrounding it should grow also if | |
| 442 | 1274 possible. |
| 434 | 1275 |
| 1276 What metrics are important? | |
| 1277 1. Actual width and height. | |
| 442 | 1278 |
| 434 | 1279 2. Whether the width and height are what the widget actually wants, or |
| 442 | 1280 whether it can grow or shrink. |
| 434 | 1281 |
| 1282 Text glyphs are particularly troublesome since their metrics depend | |
| 1283 on the context in which they are being viewed. For instance they | |
| 1284 can appear differently depending on the window face, frame face or | |
| 440 | 1285 glyph face. In order to simplify this text glyphs can now only have |
| 1286 a glyph-face or image-instance face. All other glyphs are | |
| 1287 essentially fixed in appearance. Perhaps the problem is that text | |
| 1288 glyphs are cached on a device basis like most other glyphs. Instead | |
| 1289 they should be cached per-window and then the instance would be | |
| 1290 fixed and we wouldn't have to mess around with font metrics and the | |
| 863 | 1291 rest. |
| 1292 | |
| 1293 Another sizing problem is alignment. We provide layout widgets that | |
| 1294 allow users to stack widgets vertically or horizontally. These | |
| 1295 layouts also allow the widgets to be centered (space evenly | |
| 1296 distributed), left or right justified (fixed spacing widgets | |
| 3094 | 1297 stacked against the left, right, top or bottom edge). Unfortunately |
| 863 | 1298 this doesn't allow widgets in different layouts to be aligned. For |
| 1299 instance how should the search dialog be organized for alignment? | |
| 1300 The obvious choice of two vertical columns does not work since the | |
| 1301 size of individual widgets will affect where they get placed. The | |
| 1302 same is true for several rows of widgets. To solve this problem we | |
| 1303 introduce the notion of `logical_unit_height'. This is a size | |
|
5384
3889ef128488
Fix misspelled words, and some grammar, across the entire source tree.
Jerry James <james@xemacs.org>
parents:
5176
diff
changeset
|
1304 quantity that is designed to be big enough to accommodate the |
| 863 | 1305 largest `single height unit'. The function |
| 1306 widget_logical_unit_height() determines the value of this in | |
| 1307 pixels. It is dependent on the widget face and some combination of | |
| 1308 spacing and border-width. Thus if users specify left or right | |
| 1309 justification in a vertical layout they get something in logical | |
| 1310 units. To simplify this the functions | |
| 1311 `widget-logical-to-character-height' and | |
| 1312 `widget-logical-to-character-width' allow conversion between | |
| 1313 characters and logical units so that frames can be sized | |
| 1314 appropriately. */ | |
| 440 | 1315 |
| 1065 | 1316 /* Query the geometry of a layout widget. */ |
| 428 | 1317 static void |
| 442 | 1318 layout_query_geometry (Lisp_Object image_instance, int* width, |
| 1319 int* height, enum image_instance_geometry disp, | |
| 2286 | 1320 Lisp_Object UNUSED (domain)) |
| 428 | 1321 { |
| 440 | 1322 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
| 1323 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest; | |
| 1324 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0; | |
| 863 | 1325 int gheight, gwidth, luh; |
| 442 | 1326 |
| 1327 /* If we are not initialized then we won't have any children. */ | |
| 1328 if (!IMAGE_INSTANCE_INITIALIZED (ii)) | |
| 1329 return; | |
| 1330 | |
| 1331 /* First just set up what we already have. */ | |
| 1332 if (width) *width = IMAGE_INSTANCE_WIDTH (ii); | |
| 1333 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii); | |
| 1334 | |
| 1335 /* If we are not allowed to dynamically size then return. */ | |
| 1336 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) | |
| 1337 && | |
| 1338 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) | |
| 1339 return; | |
| 1340 | |
| 863 | 1341 luh = widget_logical_unit_height (ii); |
| 1342 | |
| 442 | 1343 /* Pick up the border text if we have one. */ |
| 1344 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) | |
| 1345 { | |
| 1346 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp, | |
| 1347 image_instance); | |
| 863 | 1348 ph_adjust = gheight; |
| 1068 | 1349 /* Include text width in vertical layouts. */ |
| 1350 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL) | |
| 1351 maxpw = gwidth + BORDER_FIDDLE_FACTOR; | |
| 442 | 1352 items = XCDR (items); |
| 1353 } | |
| 440 | 1354 |
| 1355 /* Flip through the items to work out how much stuff we have to display */ | |
| 1356 LIST_LOOP (rest, items) | |
| 1357 { | |
| 1358 Lisp_Object glyph = XCAR (rest); | |
| 442 | 1359 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance); |
| 440 | 1360 |
| 442 | 1361 nitems ++; |
| 863 | 1362 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) |
| 440 | 1363 { |
| 442 | 1364 maxph = max (maxph, gheight); |
| 1365 maxpw += gwidth; | |
| 440 | 1366 } |
| 1367 else | |
| 1368 { | |
| 442 | 1369 maxpw = max (maxpw, gwidth); |
| 1370 maxph += gheight; | |
| 440 | 1371 } |
| 1372 } | |
| 428 | 1373 |
| 442 | 1374 /* Work out minimum space we need to fit all the items. This could |
| 1375 have been fixed by the user. */ | |
| 1318 | 1376 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) |
| 1377 { | |
| 1065 | 1378 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii))) |
| 1318 | 1379 { |
| 1065 | 1380 Lisp_Object dynamic_width = |
| 1318 | 1381 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)); |
| 1065 | 1382 if (INTP (dynamic_width)) |
| 1318 | 1383 *width = XINT (dynamic_width); |
| 1384 } | |
| 1065 | 1385 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) |
| 1318 | 1386 { |
| 1065 | 1387 *width = maxpw + ((nitems + 1) * widget_instance_border_width (ii) + |
| 1388 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2; | |
| 1318 | 1389 } |
| 1065 | 1390 else |
| 1318 | 1391 { |
| 1065 | 1392 *width = maxpw + 2 * (widget_instance_border_width (ii) * 2 + |
| 1393 IMAGE_INSTANCE_MARGIN_WIDTH (ii)); | |
| 1318 | 1394 } |
| 1065 | 1395 } |
| 1396 | |
| 440 | 1397 /* Work out vertical spacings. */ |
| 1318 | 1398 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) |
| 1399 { | |
| 1065 | 1400 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) |
| 1318 | 1401 { |
| 1065 | 1402 Lisp_Object dynamic_height = |
| 1318 | 1403 eval_within_redisplay (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)); |
| 1065 | 1404 if (INTP (dynamic_height)) |
| 1318 | 1405 *height = XINT (dynamic_height); |
| 1406 } | |
| 1065 | 1407 else if (IMAGE_INSTANCE_SUBWINDOW_LOGICAL_LAYOUT (ii)) |
| 1318 | 1408 { |
| 1065 | 1409 *height = nitems * luh + ph_adjust; |
| 1318 | 1410 } |
| 1065 | 1411 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL) |
| 1318 | 1412 { |
| 1065 | 1413 *height = maxph + ((nitems + 1) * widget_instance_border_width (ii) + |
| 1414 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; | |
| 1318 | 1415 } |
| 1065 | 1416 else |
| 1318 | 1417 { |
| 1065 | 1418 *height = maxph + (2 * widget_instance_border_width (ii) + |
| 1419 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; | |
| 1318 | 1420 } |
| 1065 | 1421 } |
| 863 | 1422 #ifdef DEBUG_WIDGET_OUTPUT |
| 1423 stderr_out ("layout wants %dx%d\n", *width, *height); | |
| 1424 #endif | |
| 440 | 1425 } |
| 1426 | |
| 442 | 1427 int |
| 1428 layout_layout (Lisp_Object image_instance, | |
| 2286 | 1429 int width, int height, int UNUSED (xoffset), int yoffset, |
| 1430 Lisp_Object UNUSED (domain)) | |
| 440 | 1431 { |
| 1432 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1433 Lisp_Object rest; | |
| 1434 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); | |
| 1435 int x, y, maxph = 0, maxpw = 0, nitems = 0, | |
| 1436 horiz_spacing, vert_spacing, ph_adjust = 0; | |
| 442 | 1437 int gheight, gwidth; |
| 863 | 1438 /* See comments in widget_logical_unit_height(). */ |
| 1439 int luh = widget_logical_unit_height (ii); | |
| 442 | 1440 |
| 1441 /* If we are not initialized then we won't have any children. */ | |
| 1442 if (!IMAGE_INSTANCE_INITIALIZED (ii)) | |
| 1443 return 0; | |
| 428 | 1444 |
| 863 | 1445 #ifdef DEBUG_WIDGET_OUTPUT |
| 1446 stderr_out ("layout output %dx%d\n", width, height); | |
| 1447 #endif | |
| 1448 | |
| 1449 /* Pick up the border text if we have one. A border can have the | |
| 1450 values Qetched_in, Qetched_out, Qbevel_in, Qbevel_out or an | |
| 1451 integer. The first four just affect the display properties of the | |
| 1452 border that is drawn. The last is an offset and implies that the | |
| 1453 first item in the list of subcontrols is a text control that | |
| 1454 should be displayed on the border. */ | |
| 442 | 1455 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) |
| 1456 { | |
| 1457 Lisp_Object border = XCAR (items); | |
| 1458 items = XCDR (items); | |
| 1459 glyph_query_geometry (border, &gwidth, &gheight, | |
| 1460 IMAGE_DESIRED_GEOMETRY, image_instance); | |
| 863 | 1461 /* The vertical offset for subsequent items is the full height |
| 1462 of the border glyph. */ | |
| 1463 ph_adjust = gheight; | |
| 1464 /* The offset for the border is half the glyph height. */ | |
| 1465 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (gheight / 2); | |
| 442 | 1466 |
| 1467 /* #### Really, what should this be? */ | |
| 1068 | 1468 glyph_do_layout (border, gwidth, gheight, BORDER_FIDDLE_FACTOR, 0, |
| 442 | 1469 image_instance); |
| 1470 } | |
| 1471 | |
| 1472 /* Flip through the items to work out how much stuff we have to display. */ | |
| 428 | 1473 LIST_LOOP (rest, items) |
| 1474 { | |
| 1475 Lisp_Object glyph = XCAR (rest); | |
| 440 | 1476 |
| 442 | 1477 glyph_query_geometry (glyph, &gwidth, &gheight, |
| 1478 IMAGE_DESIRED_GEOMETRY, image_instance); | |
| 1479 nitems ++; | |
| 1480 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) | |
| 1481 == LAYOUT_HORIZONTAL) | |
| 428 | 1482 { |
| 442 | 1483 maxph = max (maxph, gheight); |
| 1484 maxpw += gwidth; | |
| 428 | 1485 } |
| 440 | 1486 else |
| 428 | 1487 { |
| 442 | 1488 maxpw = max (maxpw, gwidth); |
| 1489 maxph += gheight; | |
| 428 | 1490 } |
| 1491 } | |
| 1492 | |
| 1493 /* work out spacing between items and bounds of the layout */ | |
| 440 | 1494 if (width < maxpw) |
| 428 | 1495 /* The user wants a smaller space than the largest item, so we |
| 1496 just provide default spacing and will let the output routines | |
| 863 | 1497 clip. */ |
| 1498 horiz_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)); | |
| 442 | 1499 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) |
| 863 | 1500 == LAYOUT_HORIZONTAL) |
| 428 | 1501 /* We have a larger area to display in so distribute the space |
| 1502 evenly. */ | |
| 442 | 1503 horiz_spacing = (width - (maxpw + |
| 1504 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) | |
| 1505 / (nitems + 1); | |
| 428 | 1506 else |
| 442 | 1507 horiz_spacing = (width - maxpw) / 2 |
| 1508 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); | |
| 428 | 1509 |
| 863 | 1510 /* We are trying here to get widgets to line up when they are left |
| 1511 or right justified vertically. This means that we must position | |
| 1512 widgets on logical unit boundaries, even though their height may | |
| 1513 be greater or less than a logical unit. In order to avoid | |
| 1514 clipping we need to determine how big the widget wants to be and | |
| 1515 then allocate as many logical units as necessary in order to | |
| 1516 accommodate it. */ | |
| 440 | 1517 if (height < maxph) |
| 863 | 1518 vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2; |
| 442 | 1519 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) |
| 440 | 1520 == LAYOUT_VERTICAL) |
| 863 | 1521 { |
| 1522 if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) | |
| 1523 vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2; | |
| 1524 else | |
| 1525 vert_spacing = (height - (maxph + ph_adjust + | |
| 1526 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) | |
| 1527 / (nitems + 1); | |
| 1528 } | |
| 428 | 1529 else |
| 442 | 1530 vert_spacing = (height - (maxph + ph_adjust)) / 2 |
| 1531 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); | |
| 428 | 1532 |
| 863 | 1533 y = yoffset = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii); |
| 442 | 1534 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii); |
| 428 | 1535 |
| 1536 /* Now flip through putting items where we want them, paying | |
| 440 | 1537 attention to justification. Make sure we don't mess with the |
| 1538 border glyph. */ | |
| 428 | 1539 LIST_LOOP (rest, items) |
| 1540 { | |
| 1541 Lisp_Object glyph = XCAR (rest); | |
| 1542 | |
| 442 | 1543 glyph_query_geometry (glyph, &gwidth, &gheight, |
| 1544 IMAGE_DESIRED_GEOMETRY, image_instance); | |
| 1545 | |
| 863 | 1546 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) |
| 442 | 1547 { |
| 863 | 1548 if (IMAGE_INSTANCE_SUBWINDOW_BOTTOM_JUSTIFIED (ii)) |
| 442 | 1549 y = height - (gheight + vert_spacing); |
| 863 | 1550 else if (IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) |
| 442 | 1551 y = (height - gheight) / 2; |
| 1552 } | |
| 1553 else | |
| 1554 { | |
| 863 | 1555 if (IMAGE_INSTANCE_SUBWINDOW_RIGHT_JUSTIFIED (ii)) |
| 442 | 1556 x = width - (gwidth + horiz_spacing); |
| 863 | 1557 else if (IMAGE_INSTANCE_SUBWINDOW_H_CENTERED (ii)) |
| 442 | 1558 x = (width - gwidth) / 2; |
| 1559 } | |
| 1560 | |
| 1561 /* Now layout subwidgets if they require it. */ | |
| 1562 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance); | |
| 1563 | |
| 863 | 1564 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) |
| 442 | 1565 { |
| 1566 x += (gwidth + horiz_spacing); | |
| 1567 } | |
| 1568 else | |
| 1569 { | |
| 1570 y += (gheight + vert_spacing); | |
| 863 | 1571 if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) |
| 1572 { | |
| 1573 /* justified, vertical layout, try and align on logical unit | |
| 1574 boundaries. */ | |
| 1575 y = ROUND_UP (y - yoffset, luh) + yoffset; | |
| 1576 } | |
| 442 | 1577 } |
| 1578 | |
| 1579 } | |
| 1580 return 1; | |
| 1581 } | |
| 1582 | |
| 1583 /* Get the glyphs that comprise a layout. These are created internally | |
| 1584 and so are otherwise inaccessible to lisp. We need some way of getting | |
| 1585 properties from the widgets that comprise a layout and this is the | |
| 1586 simplest way of doing it. | |
| 428 | 1587 |
| 442 | 1588 #### Eventually we should allow some more intelligent access to |
| 1589 sub-widgets. */ | |
| 1590 static Lisp_Object | |
| 1591 layout_property (Lisp_Object image_instance, Lisp_Object prop) | |
| 1592 { | |
| 1593 /* This function can GC. */ | |
| 1594 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
| 1595 if (EQ (prop, Q_items)) | |
| 1596 { | |
| 1597 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) && | |
| 1598 CONSP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))) | |
| 1599 return Fcopy_sequence (XCDR | |
| 1600 (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))); | |
| 1601 else | |
| 1602 return Fcopy_sequence (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)); | |
| 428 | 1603 } |
| 442 | 1604 return Qunbound; |
| 1605 } | |
| 428 | 1606 |
| 442 | 1607 /* Layout subwindows if they are real subwindows. */ |
| 1608 static int | |
| 1609 native_layout_layout (Lisp_Object image_instance, | |
| 1610 int width, int height, int xoffset, int yoffset, | |
| 1611 Lisp_Object domain) | |
| 1612 { | |
| 1613 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); | |
| 1614 Lisp_Object rest; | |
| 1615 | |
| 1616 /* The first time this gets called, the layout will be only | |
| 1617 partially instantiated. The children get done in | |
| 1618 post_instantiate. */ | |
| 1619 if (!IMAGE_INSTANCE_INITIALIZED (ii)) | |
| 1620 return 0; | |
| 1621 | |
| 1622 /* Defining this overrides the default layout_layout so we first have to call that to get | |
| 1623 suitable instances and values set up. */ | |
| 1624 layout_layout (image_instance, width, height, xoffset, yoffset, domain); | |
| 1625 | |
| 1626 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)) | |
| 1627 { | |
| 1628 struct display_glyph_area dga; | |
| 1629 dga.xoffset = 0; | |
| 1630 dga.yoffset = 0; | |
| 1631 dga.width = IMAGE_INSTANCE_WIDTH (ii); | |
| 1632 dga.height = IMAGE_INSTANCE_HEIGHT (ii); | |
| 1633 | |
| 1634 map_subwindow (XCAR (rest), | |
| 1635 IMAGE_INSTANCE_XOFFSET (ii), | |
| 1636 IMAGE_INSTANCE_YOFFSET (ii), &dga); | |
| 1637 } | |
| 1638 return 1; | |
| 428 | 1639 } |
| 1640 | |
| 863 | 1641 DEFUN ("widget-logical-to-character-width", Fwidget_logical_to_character_width, 1, 3, 0, /* |
| 1642 Convert the width in logical widget units to characters. | |
| 3094 | 1643 Logical widget units do not take into account adjustments made for |
| 1644 layout borders, so this adjustment is approximated. | |
| 863 | 1645 */ |
| 2286 | 1646 (width, UNUSED (face), domain)) |
| 863 | 1647 { |
| 1648 int w, neww, charwidth; | |
| 1649 int border_width = DEFAULT_WIDGET_BORDER_WIDTH; | |
| 1650 | |
| 1651 if (NILP (domain)) | |
| 1652 domain = Fselected_frame (Qnil); | |
| 1653 | |
| 1654 CHECK_INT (width); | |
| 1655 w = XINT (width); | |
| 1656 | |
| 1657 if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_border_width)) | |
| 1658 border_width = DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ()); | |
| 1659 | |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
4677
diff
changeset
|
1660 default_face_font_info (domain, 0, 0, &charwidth, 0, 0); |
| 863 | 1661 neww = ROUND_UP (charwidth * w + 4 * border_width + 2 * widget_spacing (domain), |
| 1662 charwidth) / charwidth; | |
| 1663 | |
| 1664 return make_int (neww); | |
| 1665 } | |
| 1666 | |
| 1667 DEFUN ("widget-logical-to-character-height", Fwidget_logical_to_character_height, 1, 3, 0, /* | |
| 1668 Convert the height in logical widget units to characters. | |
| 3094 | 1669 Logical widget units do not take into account adjustments made for |
| 863 | 1670 layout borders, so this adjustment is approximated. |
| 1671 | |
| 1672 If the components of a widget layout are justified to the top or the | |
| 1673 bottom then they are aligned in terms of `logical units'. This is a | |
|
5384
3889ef128488
Fix misspelled words, and some grammar, across the entire source tree.
Jerry James <james@xemacs.org>
parents:
5176
diff
changeset
|
1674 size quantity that is designed to be big enough to accommodate the |
| 863 | 1675 largest `single height' widget. It is dependent on the widget face and |
| 1676 some combination of spacing and border-width. Thus if you specify top | |
| 1677 or bottom justification in a vertical layout the subcontrols are laid | |
| 1678 out one per logical unit. This allows adjoining layouts to have | |
| 1679 identical alignment for their subcontrols. | |
| 1680 | |
| 1681 Since frame sizes are measured in characters, this function allows you | |
| 1682 to do appropriate conversion between logical units and characters. | |
| 1683 */ | |
| 2286 | 1684 (height, UNUSED (face), domain)) |
| 863 | 1685 { |
| 1686 int h, newh, charheight; | |
| 1687 | |
| 1688 CHECK_INT (height); | |
| 1689 if (NILP (domain)) | |
| 1690 domain = Fselected_frame (Qnil); | |
| 1691 | |
| 1692 h = XINT (height); | |
| 1693 | |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
4677
diff
changeset
|
1694 default_face_font_info (domain, 0, 0, 0, &charheight, 0); |
| 863 | 1695 newh = ROUND_UP (logical_unit_height (Fsymbol_name (Qwidget), |
| 1696 Vwidget_face, domain) * h, charheight) | |
| 1697 / charheight; | |
| 1698 | |
| 1699 return make_int (newh); | |
| 1700 } | |
| 1701 | |
| 428 | 1702 |
| 1703 /************************************************************************/ | |
| 1704 /* initialization */ | |
| 1705 /************************************************************************/ | |
| 1706 | |
| 1707 void | |
| 1708 syms_of_glyphs_widget (void) | |
| 1709 { | |
| 442 | 1710 DEFSYMBOL (Qetched_in); |
| 1711 DEFSYMBOL (Qetched_out); | |
| 1712 DEFSYMBOL (Qbevel_in); | |
| 1713 DEFSYMBOL (Qbevel_out); | |
| 1714 DEFSYMBOL (Qmake_glyph); | |
| 863 | 1715 |
| 1716 DEFSUBR (Fwidget_logical_to_character_height); | |
| 1717 DEFSUBR (Fwidget_logical_to_character_width); | |
| 428 | 1718 } |
| 1719 | |
| 442 | 1720 #define VALID_GUI_KEYWORDS(type) do { \ |
| 1721 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \ | |
| 1722 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \ | |
| 1723 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \ | |
| 1724 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \ | |
| 1725 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \ | |
| 1726 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \ | |
| 1727 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \ | |
| 1728 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \ | |
| 1729 IIFORMAT_VALID_KEYWORD (type, Q_initial_focus, check_valid_anything); \ | |
| 1730 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \ | |
| 1731 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \ | |
| 1732 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \ | |
| 1733 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \ | |
| 1734 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \ | |
| 1735 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, \ | |
| 1736 check_valid_string_or_vector); \ | |
| 440 | 1737 } while (0) |
| 428 | 1738 |
| 442 | 1739 #define VALID_WIDGET_KEYWORDS(type) do { \ |
| 1740 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \ | |
| 1741 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \ | |
| 1742 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function); \ | |
| 1743 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function); \ | |
| 1744 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \ | |
| 440 | 1745 } while (0) |
| 428 | 1746 |
| 440 | 1747 |
| 1748 static void image_instantiator_widget (void) | |
| 1749 { /* we only do this for properties */ | |
| 428 | 1750 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget"); |
| 1751 IIFORMAT_HAS_METHOD (widget, property); | |
| 442 | 1752 IIFORMAT_HAS_METHOD (widget, update); |
| 438 | 1753 IIFORMAT_HAS_METHOD (widget, query_geometry); |
| 1754 IIFORMAT_HAS_METHOD (widget, layout); | |
| 440 | 1755 } |
| 428 | 1756 |
| 440 | 1757 static void image_instantiator_buttons (void) |
| 1758 { | |
| 428 | 1759 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button"); |
| 1760 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget); | |
| 1761 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget); | |
| 1762 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget); | |
| 442 | 1763 IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget); |
| 428 | 1764 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget); |
| 442 | 1765 IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow); |
| 1766 IIFORMAT_HAS_METHOD (button, query_geometry); | |
| 440 | 1767 IIFORMAT_VALID_KEYWORD (button, |
| 442 | 1768 Q_image, check_valid_instantiator); |
| 428 | 1769 VALID_WIDGET_KEYWORDS (button); |
| 1770 VALID_GUI_KEYWORDS (button); | |
| 440 | 1771 } |
| 428 | 1772 |
| 440 | 1773 static void image_instantiator_edit_fields (void) |
| 1774 { | |
| 428 | 1775 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field"); |
| 1776 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget); | |
| 1777 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget); | |
| 1778 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget); | |
| 442 | 1779 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget); |
| 1780 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow); | |
| 863 | 1781 IIFORMAT_HAS_METHOD (edit_field, query_geometry); |
| 428 | 1782 VALID_WIDGET_KEYWORDS (edit_field); |
| 1783 VALID_GUI_KEYWORDS (edit_field); | |
| 440 | 1784 } |
| 428 | 1785 |
| 440 | 1786 static void image_instantiator_combo_box (void) |
| 1787 { | |
| 428 | 1788 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box"); |
| 1789 IIFORMAT_HAS_METHOD (combo_box, validate); | |
| 1790 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget); | |
| 442 | 1791 IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow); |
| 1792 | |
| 428 | 1793 VALID_GUI_KEYWORDS (combo_box); |
| 1794 | |
| 1795 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int); | |
| 1796 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int); | |
| 442 | 1797 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, |
| 1798 check_valid_int_or_function); | |
| 428 | 1799 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face); |
| 442 | 1800 IIFORMAT_VALID_KEYWORD (combo_box, Q_items, check_valid_item_list); |
| 440 | 1801 } |
| 428 | 1802 |
| 440 | 1803 static void image_instantiator_scrollbar (void) |
| 1804 { | |
| 428 | 1805 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar"); |
| 1806 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget); | |
| 1807 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget); | |
| 1808 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget); | |
| 442 | 1809 IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget); |
| 1810 IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow); | |
| 428 | 1811 VALID_GUI_KEYWORDS (scrollbar); |
| 1812 | |
| 442 | 1813 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, |
| 1814 check_valid_int_or_function); | |
| 1815 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, | |
| 1816 check_valid_int_or_function); | |
| 428 | 1817 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face); |
| 440 | 1818 } |
| 428 | 1819 |
| 3094 | 1820 static void image_instantiator_progress_gauge (void) |
| 440 | 1821 { |
| 428 | 1822 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge"); |
| 1823 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget); | |
| 1824 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget); | |
| 1825 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget); | |
| 442 | 1826 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget); |
| 1827 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow); | |
| 428 | 1828 VALID_WIDGET_KEYWORDS (progress_gauge); |
| 1829 VALID_GUI_KEYWORDS (progress_gauge); | |
| 442 | 1830 |
| 1831 IIFORMAT_VALID_KEYWORD (progress_gauge, Q_value, check_valid_int); | |
| 440 | 1832 } |
| 428 | 1833 |
| 440 | 1834 static void image_instantiator_tree_view (void) |
| 1835 { | |
| 428 | 1836 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view"); |
| 1837 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); | |
| 1838 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); | |
| 438 | 1839 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget); |
| 442 | 1840 IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget); |
| 1841 IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow); | |
| 438 | 1842 IIFORMAT_HAS_METHOD (tree_view, query_geometry); |
| 428 | 1843 VALID_WIDGET_KEYWORDS (tree_view); |
| 1844 VALID_GUI_KEYWORDS (tree_view); | |
| 442 | 1845 IIFORMAT_VALID_KEYWORD (tree_view, Q_items, check_valid_item_list); |
| 440 | 1846 } |
| 428 | 1847 |
| 440 | 1848 static void image_instantiator_tab_control (void) |
| 1849 { | |
| 428 | 1850 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control"); |
| 1851 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box); | |
| 1852 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); | |
| 438 | 1853 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget); |
| 442 | 1854 IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget); |
| 1855 IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow); | |
| 438 | 1856 IIFORMAT_HAS_METHOD (tab_control, query_geometry); |
| 428 | 1857 VALID_WIDGET_KEYWORDS (tab_control); |
| 1858 VALID_GUI_KEYWORDS (tab_control); | |
| 442 | 1859 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, |
| 1860 check_valid_tab_orientation); | |
| 1861 IIFORMAT_VALID_KEYWORD (tab_control, Q_items, check_valid_item_list); | |
| 440 | 1862 } |
| 428 | 1863 |
| 440 | 1864 static void image_instantiator_labels (void) |
| 1865 { | |
| 428 | 1866 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label"); |
| 1867 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget); | |
| 438 | 1868 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget); |
| 442 | 1869 IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget); |
| 1870 IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow); | |
| 428 | 1871 VALID_WIDGET_KEYWORDS (label); |
| 1872 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); | |
| 440 | 1873 } |
| 428 | 1874 |
| 442 | 1875 #define VALID_LAYOUT_KEYWORDS(layout) \ |
| 1876 VALID_WIDGET_KEYWORDS (layout); \ | |
| 1877 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \ | |
| 1878 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \ | |
| 863 | 1879 IIFORMAT_VALID_KEYWORD (layout, Q_vertically_justify, check_valid_justification); \ |
| 1880 IIFORMAT_VALID_KEYWORD (layout, Q_horizontally_justify, check_valid_justification); \ | |
| 442 | 1881 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \ |
| 1882 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \ | |
| 1883 IIFORMAT_VALID_KEYWORD (layout, Q_items, \ | |
| 1884 check_valid_instantiator_list) | |
| 1885 | |
| 440 | 1886 static void image_instantiator_layout (void) |
| 1887 { | |
| 428 | 1888 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout"); |
| 442 | 1889 IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget); |
| 1890 IIFORMAT_HAS_METHOD (layout, instantiate); | |
| 1891 IIFORMAT_HAS_METHOD (layout, post_instantiate); | |
| 1892 IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow); | |
| 428 | 1893 IIFORMAT_HAS_METHOD (layout, normalize); |
| 440 | 1894 IIFORMAT_HAS_METHOD (layout, query_geometry); |
| 1895 IIFORMAT_HAS_METHOD (layout, layout); | |
| 442 | 1896 IIFORMAT_HAS_METHOD (layout, update); |
| 1897 IIFORMAT_HAS_METHOD (layout, property); | |
| 1898 | |
| 1899 VALID_GUI_KEYWORDS (layout); | |
| 1900 VALID_LAYOUT_KEYWORDS (layout); | |
| 1901 } | |
| 1902 | |
| 1903 static void image_instantiator_native_layout (void) | |
| 1904 { | |
| 1905 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout"); | |
| 1906 IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget); | |
| 1907 IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout); | |
| 1908 IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout); | |
| 1909 IIFORMAT_HAS_METHOD (native_layout, layout); | |
| 1910 IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow); | |
| 1911 IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout); | |
| 1912 IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout); | |
| 1913 IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout); | |
| 1914 IIFORMAT_HAS_SHARED_METHOD (native_layout, property, layout); | |
| 1915 | |
| 1916 VALID_GUI_KEYWORDS (native_layout); | |
| 1917 VALID_LAYOUT_KEYWORDS (native_layout); | |
| 428 | 1918 } |
| 1919 | |
| 1920 void | |
| 440 | 1921 image_instantiator_format_create_glyphs_widget (void) |
| 1922 { | |
| 1923 image_instantiator_widget(); | |
| 1924 image_instantiator_buttons(); | |
| 1925 image_instantiator_edit_fields(); | |
| 1926 image_instantiator_combo_box(); | |
| 1927 image_instantiator_scrollbar(); | |
| 3094 | 1928 image_instantiator_progress_gauge(); |
| 440 | 1929 image_instantiator_tree_view(); |
| 1930 image_instantiator_tab_control(); | |
| 1931 image_instantiator_labels(); | |
| 1932 image_instantiator_layout(); | |
| 442 | 1933 image_instantiator_native_layout(); |
| 440 | 1934 } |
| 1935 | |
| 1936 void | |
| 428 | 1937 reinit_vars_of_glyphs_widget (void) |
| 1938 { | |
| 1939 #ifdef DEBUG_WIDGETS | |
| 1940 debug_widget_instances = 0; | |
| 1941 #endif | |
| 1942 } | |
| 1943 | |
| 1944 void | |
| 1945 vars_of_glyphs_widget (void) | |
| 1946 { | |
| 1947 } | |
| 863 | 1948 |
| 1949 | |
| 1950 void | |
| 1951 specifier_vars_of_glyphs_widget (void) | |
| 1952 { | |
| 1953 DEFVAR_SPECIFIER ("widget-border-width", | |
| 1954 &Vwidget_border_width /* | |
| 1955 *Border width of widgets. | |
| 1956 This is a specifier; use `set-specifier' to change it. | |
| 1957 */ ); | |
| 1958 Vwidget_border_width = Fmake_specifier (Qnatnum); | |
| 1959 } |
