1 /* Widget-specific glyph objects.
2 Copyright (C) 1998, 1999, 2000 Andy Piper.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
23 /* written by Andy Piper <andy@xemacs.org> */
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);
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);
58 DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout);
59 Lisp_Object Qnative_layout;
61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
62 Lisp_Object Qmake_glyph;
65 int debug_widget_instances;
69 - tooltips for controls, especially buttons.
71 - lisp configurable layout.
74 /* In MS-Windows normal windows work in pixels, dialog boxes work in
75 dialog box units. Why? sigh. We could reuse the metrics for dialogs
76 if this were not the case. As it is we have to position things
77 pixel wise. I'm not even sure that X has this problem at least for
80 widget_possible_dest_types (void)
82 return IMAGE_WIDGET_MASK;
86 check_valid_instantiator (Lisp_Object data)
88 Lisp_Object glyph = data;
90 glyph = XSYMBOL (data)->value;
92 if (!CONSP (glyph) && !VECTORP (glyph))
93 invalid_argument ("instantiator item must be a vector", data);
97 check_valid_orientation (Lisp_Object data)
99 if (!EQ (data, Qhorizontal)
101 !EQ (data, Qvertical))
102 invalid_argument ("unknown orientation for layout", data);
106 check_valid_tab_orientation (Lisp_Object data)
115 invalid_argument ("unknown orientation for tab control", data);
119 check_valid_justification (Lisp_Object data)
121 if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter))
122 invalid_argument ("unknown justification for layout", data);
126 check_valid_border (Lisp_Object data)
128 if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out)
129 && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out)
130 && !GLYPHP (data) && !VECTORP (data))
131 invalid_argument ("unknown border style for layout", data);
135 check_valid_anything (Lisp_Object data)
140 check_valid_callback (Lisp_Object data)
143 && !COMPILED_FUNCTIONP (data)
146 invalid_argument (":callback must be a function or expression", data);
151 check_valid_int_or_function (Lisp_Object data)
153 if (!INTP (data) && !CONSP (data) && !SYMBOLP (data))
154 invalid_argument ("must be an integer or expresssion", data);
158 check_valid_symbol (Lisp_Object data)
164 check_valid_string_or_vector (Lisp_Object data)
166 if (!STRINGP (data) && !VECTORP (data))
167 invalid_argument (":descriptor must be a string or a vector", data);
171 check_valid_item_list (Lisp_Object items)
176 EXTERNAL_LIST_LOOP (rest, items)
178 if (STRINGP (XCAR (rest)))
179 CHECK_STRING (XCAR (rest));
180 else if (VECTORP (XCAR (rest)))
181 gui_parse_item_keywords (XCAR (rest));
182 else if (LISTP (XCAR (rest)))
183 check_valid_item_list (XCAR (rest));
185 invalid_argument ("Items must be vectors, lists or strings", items);
190 check_valid_instantiator_list (Lisp_Object data)
195 EXTERNAL_LIST_LOOP (rest, data)
197 check_valid_instantiator (XCAR (rest));
202 glyph_instantiator_to_glyph (Lisp_Object sym)
204 /* This function calls lisp. */
205 Lisp_Object glyph = sym;
209 /* if we have a symbol get at the actual data */
211 glyph = XSYMBOL (glyph)->value;
214 glyph = Feval (glyph);
216 /* Be really helpful to the user. */
219 glyph = call1 (Qmake_glyph, glyph);
222 /* substitute the new glyph */
223 RETURN_UNGCPRO (glyph);
227 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val)
230 /* substitute the new glyph */
231 for (i = 0; i < XVECTOR_LENGTH (inst); i++)
233 if (EQ (key, XVECTOR_DATA (inst)[i]))
235 XVECTOR_DATA (inst)[i+1] = val;
241 /* Wire widget property invocations to specific widgets. The problem
242 we are solving here is that when instantiators get converted to
243 instances they lose some type information (they just become
244 subwindows or widgets for example). For widgets we need to preserve
245 this type information so that we can do widget specific operations
246 on the instances. This is encoded in the widget type
247 field. widget_property gets invoked by decoding the primary type
248 (Qwidget), <widget>_property then invokes based on the secondary
249 type (Qedit_field for example). It is debatable whether we should
250 wire things in this generalised way rather than treating widgets
251 specially in image_instance_property. */
253 widget_property (Lisp_Object image_instance, Lisp_Object prop)
255 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
256 struct image_instantiator_methods* meths;
257 #if 0 /* The usefulness of this is dubious. */
258 /* first see if its a general property ... */
259 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
260 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
262 /* .. then try device specific methods ... */
263 meths = decode_device_ii_format (image_instance_device (image_instance),
264 IMAGE_INSTANCE_WIDGET_TYPE (ii),
266 if (meths && HAS_IIFORMAT_METH_P (meths, property))
267 return IIFORMAT_METH (meths, property, (image_instance, prop));
268 /* ... then format specific methods ... */
269 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
271 if (meths && HAS_IIFORMAT_METH_P (meths, property))
272 return IIFORMAT_METH (meths, property, (image_instance, prop));
277 /* Update the displayed properties of a widget.
279 #### This has been adapted from the original set_property functions
280 and thus reuses the state management of that. A better solution is
281 to simply re-parse the instantiator when items need updating. This
282 make comparing differences much simpler and obviates the need for a
283 lot of the state variables.
285 #### property is still a valid function since we have to be able to
286 extract information from the actual widget.
288 #### update_widget should probably be re-written to use the
289 instantiator. We probably want to keep a record of the differences
290 also to make this easy. We would also need a pending_instantiator
291 so that changes could be delayed. */
293 widget_update (Lisp_Object image_instance, Lisp_Object instantiator)
295 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
296 struct image_instantiator_methods* meths;
299 Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
300 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
301 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
302 Lisp_Object descriptor_item = Qnil;
304 GCPRO1 (descriptor_item);
306 /* Pick up any generic properties that we might need to keep hold
308 #### This is potentially bogus because it is changing the items
309 in place rather than in the pending items. */
312 IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
313 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
316 /* Retrieve the gui item information. This is easy if we have been
317 provided with a vector, more difficult if we have just been given
320 #### This is inconsistent with instantiation in that you have to
321 have the :descriptor keyword for updates in order to recognise
325 descriptor_item = gui_parse_item_keywords_no_errors (desc);
329 /* Since we are updating the instantiator could be incomplete
330 and hence the gui item descriptor not well formed. We
331 therefore try updating and discard the results if nothing
333 descriptor_item = copy_gui_item (IMAGE_INSTANCE_WIDGET_ITEM (ii));
334 if (!update_gui_item_keywords (descriptor_item, instantiator))
335 descriptor_item = Qnil;
338 /* Record new items for update. *_redisplay will do the
340 if (!EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
342 !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
346 if (NILP (descriptor_item))
347 descriptor_item = IMAGE_INSTANCE_WIDGET_ITEM (ii);
349 check_valid_item_list (items);
350 #ifdef DEBUG_WIDGET_OUTPUT
351 stderr_out ("items for widget %p updated\n",
352 IMAGE_INSTANCE_SUBWINDOW_ID (ii));
354 /* Don't set the actual items since we might decide not to use
355 the new ones (because nothing has really changed). If we did
356 set them and didn't use them then we would get into whole
357 heaps of trouble when the old items get GC'd. */
358 descriptor_item = Fcons (descriptor_item, parse_gui_item_tree_children (items));
360 /* If the descriptor was updated but not the items we need to fill
361 in the `new' items. */
362 else if (!NILP (descriptor_item)
364 CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
366 descriptor_item = Fcons
368 copy_gui_item_tree (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))));
372 if (!NILP (descriptor_item))
374 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = descriptor_item;
375 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
380 /* Now try device specific methods first ... */
381 meths = decode_device_ii_format (image_instance_device (image_instance),
382 IMAGE_INSTANCE_WIDGET_TYPE (ii),
384 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
385 /* ... then format specific methods ... */
386 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
388 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
389 #if 0 /* The usefulness of this is dubious. */
390 /* we didn't do any device specific properties, so shove the property in our plist. */
391 IMAGE_INSTANCE_WIDGET_PROPS (ii)
392 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
396 /* Like the rest of redisplay, we want widget updates to occur
397 asynchronously. Thus toolkit specific methods for setting
398 properties must be called by redisplay instead of by *_update. Thus
399 *_update records the change and this function actually implements
400 it. We want to be slightly clever about this however by supplying
401 format specific functions for the updates instead of lumping them
402 all into this function. Note that there is no need for format
403 generic functions. This is not the same as widget_update! */
405 redisplay_widget (Lisp_Object widget)
407 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
408 struct image_instantiator_methods* meths;
410 if (!WIDGET_IMAGE_INSTANCEP (widget)
411 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
412 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
415 /* Device-format specific methods - e.g. x_tab_control_redisplay () */
416 meths = decode_device_ii_format (image_instance_device (widget),
417 IMAGE_INSTANCE_WIDGET_TYPE (ii),
419 MAYBE_IIFORMAT_METH (meths, redisplay, (widget));
421 /* Device generic methods - e.g. x_redisplay_widget (). We must
422 update the widget's size as it may have been changed by the the
423 layout routines. We also do this here so that explicit resizing
424 from lisp does not result in synchronous updates. Do this last so
425 that format-specific methods have an opportunity to prevent
426 wholesale changes - e.g. rebuilding tabs. */
427 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii));
429 /* Pick up the items we recorded earlier. */
430 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
432 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
433 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
434 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
438 /* Query for a widgets desired geometry. If no type specific method is
439 provided then use the widget text to calculate sizes. */
441 widget_query_geometry (Lisp_Object image_instance,
442 int* width, int* height,
443 enum image_instance_geometry disp, Lisp_Object domain)
445 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
446 struct image_instantiator_methods* meths;
447 Lisp_Object dynamic_width = Qnil;
448 Lisp_Object dynamic_height = Qnil;
450 /* First just set up what we already have. */
451 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
452 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
454 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
456 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
458 /* .. then try device specific methods ... */
459 meths = decode_device_ii_format (image_instance_device (image_instance),
460 IMAGE_INSTANCE_WIDGET_TYPE (ii),
462 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
463 IIFORMAT_METH (meths, query_geometry, (image_instance,
468 /* ... then format specific methods ... */
469 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
471 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
472 IIFORMAT_METH (meths, query_geometry, (image_instance,
479 /* Then if we are allowed to resize the widget, make the
480 size the same as the text dimensions. */
481 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
482 IMAGE_INSTANCE_WIDGET_FACE (ii),
484 /* Adjust the size for borders. */
485 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
486 *width = w + 2 * WIDGET_BORDER_WIDTH;
487 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
488 *height = h + 2 * WIDGET_BORDER_HEIGHT;
491 /* Finish off with dynamic sizing. */
492 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
494 dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
495 if (INTP (dynamic_width))
496 *width = XINT (dynamic_width);
498 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
500 dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
501 if (INTP (dynamic_height))
502 *height = XINT (dynamic_height);
508 widget_layout (Lisp_Object image_instance,
509 int width, int height, int xoffset, int yoffset,
512 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
513 struct image_instantiator_methods* meths;
515 /* .. then try device specific methods ... */
516 meths = decode_device_ii_format (image_instance_device (image_instance),
517 IMAGE_INSTANCE_WIDGET_TYPE (ii),
519 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
520 return IIFORMAT_METH (meths, layout, (image_instance,
521 width, height, xoffset, yoffset,
525 /* ... then format specific methods ... */
526 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
528 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
529 return IIFORMAT_METH (meths, layout, (image_instance,
530 width, height, xoffset, yoffset,
537 widget_validate (Lisp_Object instantiator)
539 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
542 syntax_error ("Must supply :descriptor", instantiator);
545 gui_parse_item_keywords (desc);
547 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
548 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
549 syntax_error ("Must supply only one of :width and :pixel-width", instantiator);
551 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
552 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
553 syntax_error ("Must supply only one of :height and :pixel-height", instantiator);
557 combo_box_validate (Lisp_Object instantiator)
559 widget_validate (instantiator);
560 if (NILP (find_keyword_in_vector (instantiator, Q_items)))
561 syntax_error ("Must supply item list", instantiator);
564 /* we need to convert things like glyphs to images, eval expressions
567 widget_normalize (Lisp_Object inst, Lisp_Object console_type,
568 Lisp_Object dest_mask)
570 /* This function can call lisp */
571 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
573 /* we need to eval glyph if its an expression, we do this for the
574 same reasons we normalize file to data.
576 #### should just normalize the data. */
579 substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
586 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
588 /* initialize_subwindow_image_instance (ii);*/
589 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
590 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
591 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
592 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
593 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil;
594 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
595 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
596 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
597 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
598 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
599 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
600 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
603 /* Instantiate a button widget. Unfortunately instantiated widgets are
604 particular to a frame since they need to have a parent. It's not
605 like images where you just select the image into the context you
606 want to display it in and BitBlt it. So image instances can have a
607 many-to-one relationship with things you see, whereas widgets can
608 only be one-to-one (i.e. per frame) */
610 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
611 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
612 int dest_mask, Lisp_Object domain)
614 /* #### practically all of this should be moved to widget_update()
615 so that users can dynamically change all possible widget
617 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
618 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
619 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
620 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
621 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
622 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
623 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
624 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
625 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
626 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
627 Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width);
628 Lisp_Object ifocus = find_keyword_in_vector (instantiator, Q_initial_focus);
629 int pw=0, ph=0, tw=0, th=0;
631 /* this just does pixel type sizing */
632 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
635 if (!(dest_mask & IMAGE_WIDGET_MASK))
636 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
638 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
640 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
642 /* retrieve the fg and bg colors */
644 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
646 /* Retrieve the gui item information. This is easy if we have been
647 provided with a vector, more difficult if we have just been given
648 keywords. Note that standard gui descriptor shortcuts will not work
649 because of keyword parsing.
651 #### This is bogus in that descriptor and items share the same slot,
652 we should rationalize. */
655 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
656 gui_parse_item_keywords_no_errors (desc);
660 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
661 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
662 widget_gui_parse_item_keywords (instantiator);
665 /* Pick up the orientation before we do our first layout. */
666 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
667 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
669 /* parse more gui items out of the properties */
670 if (!NILP (items) && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
671 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
673 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
674 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
675 parse_gui_item_tree_children (items));
678 /* Normalize size information. We now only assign sizes if the user
679 gives us some explicitly, or there are some constraints that we
680 can't change later on. Otherwise we postpone sizing until query
681 geometry gets called. */
682 if (!NILP (pixwidth)) /* pixwidth takes precendent */
684 if (!INTP (pixwidth))
685 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth;
688 pw = XINT (pixwidth);
689 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
692 else if (!NILP (width))
695 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
698 if (!NILP (pixheight))
700 if (!INTP (pixheight))
701 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight;
704 ph = XINT (pixheight);
705 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
708 else if (!NILP (height) && XINT (height) > 1)
711 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
714 /* Taking the default face information when the user has specified
715 size in characters is probably as good as any since the widget
716 face is more likely to be proportional and thus give inadequate
717 results. Using character sizes can only ever be approximate
721 int charwidth, charheight;
722 default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
726 ph = charheight * th;
729 /* for a widget with an image pick up the dimensions from that */
733 pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH;
735 ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT;
736 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
737 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
740 /* Pick up the margin width. */
742 IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth);
744 IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (ii) = !NILP (ifocus);
746 /* Layout for the layout widget is premature at this point since the
747 children will not have been instantiated. We can't instantiate
748 them until the device instantiation method for the layout has
749 been executed. We do however want to record any specified
751 if (pw) IMAGE_INSTANCE_WIDTH (ii) = pw;
752 if (ph) IMAGE_INSTANCE_HEIGHT (ii) = ph;
756 widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
760 debug_widget_instances++;
761 stderr_out ("instantiated ");
762 debug_print (instantiator);
763 stderr_out ("%d widgets instantiated\n", debug_widget_instances);
767 /* Get the geometry of a button control. We need to adjust the size
768 depending on the type of button. */
770 button_query_geometry (Lisp_Object image_instance,
771 int* width, int* height,
772 enum image_instance_geometry disp, Lisp_Object domain)
774 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
776 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
777 IMAGE_INSTANCE_WIDGET_FACE (ii),
779 /* Adjust the size for borders. */
780 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
782 *width = w + 2 * WIDGET_BORDER_WIDTH;
784 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
786 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
787 /* This is an approximation to the size of the actual button bit. */
790 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
791 *height = h + 2 * WIDGET_BORDER_HEIGHT;
794 /* tree-view geometry - get the height right */
796 tree_view_query_geometry (Lisp_Object image_instance,
797 int* width, int* height,
798 enum image_instance_geometry disp, Lisp_Object domain)
800 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
801 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
806 /* #### what should this be. reconsider when X has tree views. */
807 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
808 IMAGE_INSTANCE_WIDGET_FACE (ii),
809 width, 0, 0, domain);
814 default_face_font_info (domain, 0, 0, &h, 0, 0);
815 GET_LIST_LENGTH (items, len);
820 /* Get the geometry of a tab control. This is based on the number of
821 items and text therin in the tab control. */
823 tab_control_query_geometry (Lisp_Object image_instance,
824 int* width, int* height,
825 enum image_instance_geometry disp, Lisp_Object domain)
827 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
828 Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
832 LIST_LOOP (rest, items)
836 query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
837 IMAGE_INSTANCE_WIDGET_FACE (ii),
839 tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
841 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
844 /* Fixup returned values depending on orientation. */
845 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
847 if (height) *height = tw;
848 if (width) *width = th;
852 if (height) *height = th;
853 if (width) *width = tw;
857 /* Determine whether only the order has changed for a tab. */
858 int tab_control_order_only_changed (Lisp_Object image_instance)
860 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
861 int found = 0, len, pending_len;
864 /* Degenerate case. */
865 if (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
868 /* See whether we just need a change in order. */
869 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_ITEMS (ii), len);
870 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii),
872 if (len == pending_len)
874 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
876 Lisp_Object pending_rest;
878 LIST_LOOP (pending_rest,
879 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
881 if (gui_item_equal_sans_selected (XCAR (rest),
882 XCAR (pending_rest), 0))
896 /*****************************************************************************
898 *****************************************************************************/
899 /* We need to cascade normalization.*/
901 layout_normalize (Lisp_Object inst, Lisp_Object console_type,
902 Lisp_Object dest_mask)
904 /* This function can call lisp */
905 struct gcpro gcpro1, gcpro2;
906 Lisp_Object alist = Qnil, new_items = Qnil, border;
907 /* This function can call lisp */
910 GCPRO2 (alist, new_items);
911 alist = tagged_vector_to_alist (inst);
912 items = assq_no_quit (Q_items, alist);
914 /* We need to normalize sub-objects. */
918 LIST_LOOP (rest, XCDR (items))
920 /* Substitute the new instantiator */
921 new_items = Fcons (normalize_image_instantiator (XCAR (rest),
922 console_type, dest_mask),
925 new_items = Fnreverse (new_items);
926 Fsetcdr (items, new_items);
928 /* Normalize the border spec. */
929 border = assq_no_quit (Q_border, alist);
930 if (!NILP (border) && VECTORP (XCDR (border)))
932 Fsetcdr (border, normalize_image_instantiator (XCDR (border),
933 console_type, dest_mask));
937 Lisp_Object result = alist_to_tagged_vector (XVECTOR_DATA (inst)[0],
940 RETURN_UNGCPRO (result);
944 /* Update the instances in the layout. */
946 layout_update (Lisp_Object image_instance, Lisp_Object instantiator)
948 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
949 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
950 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border);
951 Lisp_Object border = Qnil;
952 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
953 int structure_changed = 0;
956 /* We want to avoid consing if we can. This is quite awkward because
957 we have to deal with the border as well as the items. */
961 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
963 border = XCAR (children);
964 children = XCDR (children);
967 #ifdef DEBUG_WIDGET_OUTPUT
968 stderr_out ("layout updated\n");
970 /* Update the border. */
971 if (!NILP (border_inst))
973 if (VECTORP (border_inst))
975 /* We are going to be sneaky here and add the border text as
976 just another child, the layout and output routines don't know
977 this and will just display at the offsets we prescribe. */
979 call3 (Qset_glyph_image, border, border_inst,
980 IMAGE_INSTANCE_DOMAIN (ii));
983 border = Fcons (call1 (Qmake_glyph, border_inst), Qnil);
984 structure_changed = 1;
986 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
993 structure_changed = 1;
995 if (EQ (border_inst, Qt))
996 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
998 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border_inst;
1002 /* Pick up the sub-widgets. */
1006 GET_LIST_LENGTH (items, len1);
1007 GET_LIST_LENGTH (children, len2);
1008 /* The structure hasn't changed so just update the images. */
1009 if (!structure_changed && len1 == len2)
1011 /* Pick up the sub-widgets. */
1012 for (; !NILP (children); children = XCDR (children), items = XCDR (items))
1014 call3 (Qset_glyph_image, XCAR (children), XCAR (items),
1015 IMAGE_INSTANCE_DOMAIN (ii));
1018 /* The structure has changed so start over. */
1021 /* Instantiate any new glyphs. */
1022 for (; !NILP (items); items = XCDR (items))
1024 /* #### We really want to use call_with_suspended_errors
1025 here, but it won't allow us to call lisp. */
1026 border = Fcons (call1 (Qmake_glyph, XCAR (items)), border);
1028 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Fnreverse (border);
1035 layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1036 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1037 int dest_mask, Lisp_Object domain)
1039 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1040 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
1042 #ifdef DEBUG_WIDGET_OUTPUT
1043 stderr_out ("layout instantiated\n");
1045 /* Do widget type instantiation first. */
1046 widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
1051 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
1054 /* Get child glyphs and finish instantiation. We can't do image
1055 instance children yet as we might not have a containing
1057 layout_update (image_instance, instantiator);
1061 layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1066 /* Layout widget. Sizing commentary: we have a number of problems that
1067 we would like to address. Some consider some of these more
1068 important than others. It used to be that size information was
1069 determined at instantiation time and was then fixed forever
1070 after. Generally this is not what we want. Users want size to be
1071 "big enough" to accommodate whatever they are trying to show and
1072 this is dependent on text length, lines, font metrics etc. Of
1073 course these attributes can change dynamically and so the size
1074 should changed dynamically also. Only in a few limited cases should
1075 the size be fixed and remain fixed. Of course this actually means
1076 that we don't really want to specify the size *at all* for most
1077 widgets - we want it to be discovered dynamically. Thus we can
1078 envisage the following scenarios:
1080 1. A button is sized to accommodate its text, the text changes and the
1081 button should change size also.
1083 2. A button is given an explicit size. Its size should never change.
1085 3. Layout is put inside an area. The size of the area changes, the
1086 layout should change with it.
1088 4. A button grows to accommodate additional text. The whitespace
1089 around it should be modified to cope with the new layout
1092 5. A button grows. The area surrounding it should grow also if
1095 What metrics are important?
1096 1. Actual width and height.
1098 2. Whether the width and height are what the widget actually wants, or
1099 whether it can grow or shrink.
1101 Text glyphs are particularly troublesome since their metrics depend
1102 on the context in which they are being viewed. For instance they
1103 can appear differently depending on the window face, frame face or
1104 glyph face. In order to simplify this text glyphs can now only have
1105 a glyph-face or image-instance face. All other glyphs are
1106 essentially fixed in appearance. Perhaps the problem is that text
1107 glyphs are cached on a device basis like most other glyphs. Instead
1108 they should be cached per-window and then the instance would be
1109 fixed and we wouldn't have to mess around with font metrics and the
1112 /* Query the geometry of a layout widget. We assume that we can only
1113 get here if the size is not already fixed. */
1115 layout_query_geometry (Lisp_Object image_instance, int* width,
1116 int* height, enum image_instance_geometry disp,
1119 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1120 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
1121 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
1122 int gheight, gwidth;
1124 /* If we are not initialized then we won't have any children. */
1125 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1128 /* First just set up what we already have. */
1129 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
1130 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
1132 /* If we are not allowed to dynamically size then return. */
1133 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
1135 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
1138 /* Pick up the border text if we have one. */
1139 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1141 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp,
1143 ph_adjust = gheight / 2;
1144 items = XCDR (items);
1147 /* Flip through the items to work out how much stuff we have to display */
1148 LIST_LOOP (rest, items)
1150 Lisp_Object glyph = XCAR (rest);
1151 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance);
1154 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1155 == LAYOUT_HORIZONTAL)
1157 maxph = max (maxph, gheight);
1162 maxpw = max (maxpw, gwidth);
1167 /* Work out minimum space we need to fit all the items. This could
1168 have been fixed by the user. */
1169 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
1171 Lisp_Object dynamic_width =
1172 Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
1173 if (INTP (dynamic_width))
1174 *width = XINT (dynamic_width);
1176 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1177 == LAYOUT_HORIZONTAL)
1178 *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH +
1179 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
1181 *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 +
1182 IMAGE_INSTANCE_MARGIN_WIDTH (ii));
1184 /* Work out vertical spacings. */
1185 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
1187 Lisp_Object dynamic_height =
1188 Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
1189 if (INTP (dynamic_height))
1190 *height = XINT (dynamic_height);
1192 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1194 *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT +
1195 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1197 *height = maxph + (2 * WIDGET_BORDER_HEIGHT +
1198 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1202 layout_layout (Lisp_Object image_instance,
1203 int width, int height, int xoffset, int yoffset,
1206 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1208 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
1209 int x, y, maxph = 0, maxpw = 0, nitems = 0,
1210 horiz_spacing, vert_spacing, ph_adjust = 0;
1211 int gheight, gwidth;
1213 /* If we are not initialized then we won't have any children. */
1214 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1217 /* Pick up the border text if we have one. */
1218 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1220 Lisp_Object border = XCAR (items);
1221 items = XCDR (items);
1222 glyph_query_geometry (border, &gwidth, &gheight,
1223 IMAGE_DESIRED_GEOMETRY, image_instance);
1224 ph_adjust = gheight / 2;
1225 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
1227 /* #### Really, what should this be? */
1228 glyph_do_layout (border, gwidth, gheight, 10, 0,
1232 /* Flip through the items to work out how much stuff we have to display. */
1233 LIST_LOOP (rest, items)
1235 Lisp_Object glyph = XCAR (rest);
1237 glyph_query_geometry (glyph, &gwidth, &gheight,
1238 IMAGE_DESIRED_GEOMETRY, image_instance);
1240 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1241 == LAYOUT_HORIZONTAL)
1243 maxph = max (maxph, gheight);
1248 maxpw = max (maxpw, gwidth);
1253 /* work out spacing between items and bounds of the layout */
1255 /* The user wants a smaller space than the largest item, so we
1256 just provide default spacing and will let the output routines
1258 horiz_spacing = WIDGET_BORDER_WIDTH * 2;
1259 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1260 == LAYOUT_HORIZONTAL)
1261 /* We have a larger area to display in so distribute the space
1263 horiz_spacing = (width - (maxpw +
1264 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1267 horiz_spacing = (width - maxpw) / 2
1268 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1271 vert_spacing = WIDGET_BORDER_HEIGHT * 2;
1272 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1274 vert_spacing = (height - (maxph + ph_adjust +
1275 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1278 vert_spacing = (height - (maxph + ph_adjust)) / 2
1279 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1281 y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1282 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1284 /* Now flip through putting items where we want them, paying
1285 attention to justification. Make sure we don't mess with the
1287 LIST_LOOP (rest, items)
1289 Lisp_Object glyph = XCAR (rest);
1291 glyph_query_geometry (glyph, &gwidth, &gheight,
1292 IMAGE_DESIRED_GEOMETRY, image_instance);
1294 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1295 == LAYOUT_HORIZONTAL)
1297 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1298 == LAYOUT_JUSTIFY_RIGHT)
1299 y = height - (gheight + vert_spacing);
1300 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1301 == LAYOUT_JUSTIFY_CENTER)
1302 y = (height - gheight) / 2;
1306 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1307 == LAYOUT_JUSTIFY_RIGHT)
1308 x = width - (gwidth + horiz_spacing);
1309 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1310 == LAYOUT_JUSTIFY_CENTER)
1311 x = (width - gwidth) / 2;
1314 /* Now layout subwidgets if they require it. */
1315 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance);
1317 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1318 == LAYOUT_HORIZONTAL)
1320 x += (gwidth + horiz_spacing);
1324 y += (gheight + vert_spacing);
1331 /* Get the glyphs that comprise a layout. These are created internally
1332 and so are otherwise inaccessible to lisp. We need some way of getting
1333 properties from the widgets that comprise a layout and this is the
1334 simplest way of doing it.
1336 #### Eventually we should allow some more intelligent access to
1339 layout_property (Lisp_Object image_instance, Lisp_Object prop)
1341 /* This function can GC. */
1342 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1343 if (EQ (prop, Q_items))
1345 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) &&
1346 CONSP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)))
1347 return Fcopy_sequence (XCDR
1348 (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)));
1350 return Fcopy_sequence (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii));
1355 /* Layout subwindows if they are real subwindows. */
1357 native_layout_layout (Lisp_Object image_instance,
1358 int width, int height, int xoffset, int yoffset,
1361 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1364 /* The first time this gets called, the layout will be only
1365 partially instantiated. The children get done in
1366 post_instantiate. */
1367 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1370 /* Defining this overrides the default layout_layout so we first have to call that to get
1371 suitable instances and values set up. */
1372 layout_layout (image_instance, width, height, xoffset, yoffset, domain);
1374 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))
1376 struct display_glyph_area dga;
1379 dga.width = IMAGE_INSTANCE_WIDTH (ii);
1380 dga.height = IMAGE_INSTANCE_HEIGHT (ii);
1382 map_subwindow (XCAR (rest),
1383 IMAGE_INSTANCE_XOFFSET (ii),
1384 IMAGE_INSTANCE_YOFFSET (ii), &dga);
1390 /************************************************************************/
1391 /* initialization */
1392 /************************************************************************/
1395 syms_of_glyphs_widget (void)
1397 DEFSYMBOL (Qetched_in);
1398 DEFSYMBOL (Qetched_out);
1399 DEFSYMBOL (Qbevel_in);
1400 DEFSYMBOL (Qbevel_out);
1401 DEFSYMBOL (Qmake_glyph);
1404 #define VALID_GUI_KEYWORDS(type) do { \
1405 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \
1406 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
1407 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
1408 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
1409 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \
1410 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
1411 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
1412 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
1413 IIFORMAT_VALID_KEYWORD (type, Q_initial_focus, check_valid_anything); \
1414 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
1415 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
1416 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
1417 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \
1418 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \
1419 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, \
1420 check_valid_string_or_vector); \
1423 #define VALID_WIDGET_KEYWORDS(type) do { \
1424 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
1425 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
1426 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function); \
1427 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function); \
1428 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \
1432 static void image_instantiator_widget (void)
1433 { /* we only do this for properties */
1434 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1435 IIFORMAT_HAS_METHOD (widget, property);
1436 IIFORMAT_HAS_METHOD (widget, update);
1437 IIFORMAT_HAS_METHOD (widget, query_geometry);
1438 IIFORMAT_HAS_METHOD (widget, layout);
1441 static void image_instantiator_buttons (void)
1443 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1444 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1445 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1446 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1447 IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget);
1448 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1449 IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow);
1450 IIFORMAT_HAS_METHOD (button, query_geometry);
1451 IIFORMAT_VALID_KEYWORD (button,
1452 Q_image, check_valid_instantiator);
1453 VALID_WIDGET_KEYWORDS (button);
1454 VALID_GUI_KEYWORDS (button);
1457 static void image_instantiator_edit_fields (void)
1459 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1460 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1461 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1462 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1463 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
1464 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
1465 VALID_WIDGET_KEYWORDS (edit_field);
1466 VALID_GUI_KEYWORDS (edit_field);
1469 static void image_instantiator_combo_box (void)
1471 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1472 IIFORMAT_HAS_METHOD (combo_box, validate);
1473 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1474 IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow);
1476 VALID_GUI_KEYWORDS (combo_box);
1478 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1479 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1480 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width,
1481 check_valid_int_or_function);
1482 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1483 IIFORMAT_VALID_KEYWORD (combo_box, Q_items, check_valid_item_list);
1486 static void image_instantiator_scrollbar (void)
1488 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1489 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1490 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1491 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1492 IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget);
1493 IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow);
1494 VALID_GUI_KEYWORDS (scrollbar);
1496 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width,
1497 check_valid_int_or_function);
1498 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height,
1499 check_valid_int_or_function);
1500 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1503 static void image_instantiator_progress_guage (void)
1505 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1506 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1507 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1508 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1509 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
1510 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
1511 VALID_WIDGET_KEYWORDS (progress_gauge);
1512 VALID_GUI_KEYWORDS (progress_gauge);
1514 IIFORMAT_VALID_KEYWORD (progress_gauge, Q_value, check_valid_int);
1517 static void image_instantiator_tree_view (void)
1519 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1520 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1521 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1522 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1523 IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
1524 IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
1525 IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1526 VALID_WIDGET_KEYWORDS (tree_view);
1527 VALID_GUI_KEYWORDS (tree_view);
1528 IIFORMAT_VALID_KEYWORD (tree_view, Q_items, check_valid_item_list);
1531 static void image_instantiator_tab_control (void)
1533 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1534 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1535 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1536 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1537 IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
1538 IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
1539 IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1540 VALID_WIDGET_KEYWORDS (tab_control);
1541 VALID_GUI_KEYWORDS (tab_control);
1542 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation,
1543 check_valid_tab_orientation);
1544 IIFORMAT_VALID_KEYWORD (tab_control, Q_items, check_valid_item_list);
1547 static void image_instantiator_labels (void)
1549 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1550 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1551 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1552 IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget);
1553 IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow);
1554 VALID_WIDGET_KEYWORDS (label);
1555 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1558 #define VALID_LAYOUT_KEYWORDS(layout) \
1559 VALID_WIDGET_KEYWORDS (layout); \
1560 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \
1561 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \
1562 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \
1563 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \
1564 IIFORMAT_VALID_KEYWORD (layout, Q_items, \
1565 check_valid_instantiator_list)
1567 static void image_instantiator_layout (void)
1569 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1570 IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget);
1571 IIFORMAT_HAS_METHOD (layout, instantiate);
1572 IIFORMAT_HAS_METHOD (layout, post_instantiate);
1573 IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow);
1574 IIFORMAT_HAS_METHOD (layout, normalize);
1575 IIFORMAT_HAS_METHOD (layout, query_geometry);
1576 IIFORMAT_HAS_METHOD (layout, layout);
1577 IIFORMAT_HAS_METHOD (layout, update);
1578 IIFORMAT_HAS_METHOD (layout, property);
1580 VALID_GUI_KEYWORDS (layout);
1581 VALID_LAYOUT_KEYWORDS (layout);
1584 static void image_instantiator_native_layout (void)
1586 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout");
1587 IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget);
1588 IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout);
1589 IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout);
1590 IIFORMAT_HAS_METHOD (native_layout, layout);
1591 IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow);
1592 IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout);
1593 IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout);
1594 IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout);
1595 IIFORMAT_HAS_SHARED_METHOD (native_layout, property, layout);
1597 VALID_GUI_KEYWORDS (native_layout);
1598 VALID_LAYOUT_KEYWORDS (native_layout);
1602 image_instantiator_format_create_glyphs_widget (void)
1604 image_instantiator_widget();
1605 image_instantiator_buttons();
1606 image_instantiator_edit_fields();
1607 image_instantiator_combo_box();
1608 image_instantiator_scrollbar();
1609 image_instantiator_progress_guage();
1610 image_instantiator_tree_view();
1611 image_instantiator_tab_control();
1612 image_instantiator_labels();
1613 image_instantiator_layout();
1614 image_instantiator_native_layout();
1618 reinit_vars_of_glyphs_widget (void)
1620 #ifdef DEBUG_WIDGETS
1621 debug_widget_instances = 0;
1626 vars_of_glyphs_widget (void)
1628 reinit_vars_of_glyphs_widget ();