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