Mercurial > hg > xemacs-beta
annotate src/glyphs-widget.c @ 5626:eb41da9b4469
More documentation about glyphs cache coherency problem.
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2011-12-27 Didier Verna <didier@xemacs.org>
* glyphs.c (update_image_instance):
* glyphs.c (image_instantiate): More comments about the current
glyphs cache coherency problem.
author | Didier Verna <didier@xemacs.org> |
---|---|
date | Tue, 27 Dec 2011 21:59:03 +0100 |
parents | 56144c8593a8 |
children |
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 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
168 if (!FIXNUMP (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)); | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
581 if (FIXNUMP (dynamic_width)) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
582 *width = XFIXNUM (dynamic_width); |
442 | 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)); | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
588 if (FIXNUMP (dynamic_height)) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
589 *height = XFIXNUM (dynamic_height); |
442 | 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 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
773 if (!FIXNUMP (pixwidth)) |
442 | 774 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth; |
775 else | |
776 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
777 pw = XFIXNUM (pixwidth); |
442 | 778 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; |
779 } | |
438 | 780 } |
781 else if (!NILP (width)) | |
782 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
783 tw = XFIXNUM (width); |
438 | 784 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; |
785 } | |
786 | |
428 | 787 if (!NILP (pixheight)) |
438 | 788 { |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
789 if (!FIXNUMP (pixheight)) |
442 | 790 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight; |
791 else | |
792 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
793 ph = XFIXNUM (pixheight); |
442 | 794 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; |
795 } | |
438 | 796 } |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
797 else if (!NILP (height) && XFIXNUM (height) > 1) |
438 | 798 { |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
799 th = XFIXNUM (height); |
438 | 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)) | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
851 IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XFIXNUM (mwidth); |
442 | 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 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1141 if (FIXNUMP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) |
442 | 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 } | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1166 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_fixnum (0); |
442 | 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. */ |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1344 if (FIXNUMP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) |
442 | 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)); |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1382 if (FIXNUMP (dynamic_width)) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1383 *width = XFIXNUM (dynamic_width); |
1318 | 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)); |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1404 if (FIXNUMP (dynamic_height)) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1405 *height = XFIXNUM (dynamic_height); |
1318 | 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. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1455 if (FIXNUMP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) |
442 | 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. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1465 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_fixnum (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 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1597 if (FIXNUMP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) && |
442 | 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 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1654 CHECK_FIXNUM (width); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1655 w = XFIXNUM (width); |
863 | 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 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1664 return make_fixnum (neww); |
863 | 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 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1688 CHECK_FIXNUM (height); |
863 | 1689 if (NILP (domain)) |
1690 domain = Fselected_frame (Qnil); | |
1691 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1692 h = XFIXNUM (height); |
863 | 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 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
1699 return make_fixnum (newh); |
863 | 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 } |