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);
59 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
60 Lisp_Object Q_image, Q_text, Q_orientation, Q_justify, Q_border;
61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
62 Lisp_Object Vwidget_callback_current_channel;
63 Lisp_Object Qwidget_callback_current_channel;
66 int debug_widget_instances;
70 - tooltips for controls, especially buttons.
72 - lisp configurable layout.
75 /* In MS-Windows normal windows work in pixels, dialog boxes work in
76 dialog box units. Why? sigh. We could reuse the metrics for dialogs
77 if this were not the case. As it is we have to position things
78 pixel wise. I'm not even sure that X has this problem at least for
81 widget_possible_dest_types (void)
83 return IMAGE_WIDGET_MASK;
87 check_valid_glyph_or_instantiator (Lisp_Object data)
89 Lisp_Object glyph = data;
91 glyph = XSYMBOL (data)->value;
93 if (IMAGE_INSTANCEP (glyph))
94 CHECK_IMAGE_INSTANCE (glyph);
95 else if (!CONSP (glyph) && !VECTORP (glyph))
96 CHECK_BUFFER_GLYPH (glyph);
100 check_valid_orientation (Lisp_Object data)
102 if (!EQ (data, Qhorizontal)
104 !EQ (data, Qvertical))
105 signal_simple_error ("unknown orientation for layout", data);
109 check_valid_tab_orientation (Lisp_Object data)
118 signal_simple_error ("unknown orientation for tab control", data);
122 check_valid_justification (Lisp_Object data)
124 if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter))
125 signal_simple_error ("unknown justification for layout", data);
129 check_valid_border (Lisp_Object data)
131 if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out)
132 && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out)
133 && !GLYPHP (data) && !VECTORP (data))
134 signal_simple_error ("unknown border style for layout", data);
138 check_valid_anything (Lisp_Object data)
143 check_valid_callback (Lisp_Object data)
146 && !COMPILED_FUNCTIONP (data)
149 signal_simple_error (":callback must be a function or expression", data);
154 check_valid_int_or_function (Lisp_Object data)
156 if (!INTP (data) && !CONSP (data))
157 signal_simple_error ("must be an integer or expresssion", data);
161 check_valid_symbol (Lisp_Object data)
167 check_valid_string_or_vector (Lisp_Object data)
169 if (!STRINGP (data) && !VECTORP (data))
170 signal_simple_error (":descriptor must be a string or a vector", data);
174 check_valid_item_list_1 (Lisp_Object items)
179 EXTERNAL_LIST_LOOP (rest, items)
181 if (STRINGP (XCAR (rest)))
182 CHECK_STRING (XCAR (rest));
183 else if (VECTORP (XCAR (rest)))
184 gui_parse_item_keywords (XCAR (rest));
185 else if (LISTP (XCAR (rest)))
186 check_valid_item_list_1 (XCAR (rest));
188 signal_simple_error ("Items must be vectors, lists or strings", items);
193 check_valid_item_list (Lisp_Object data)
197 Fcheck_valid_plist (data);
198 items = Fplist_get (data, Q_items, Qnil);
200 check_valid_item_list_1 (items);
204 check_valid_glyph_or_instantiator_list (Lisp_Object data)
209 EXTERNAL_LIST_LOOP (rest, data)
211 check_valid_glyph_or_instantiator (XCAR (rest));
216 glyph_instantiator_to_glyph (Lisp_Object sym)
218 /* This function calls lisp. */
219 Lisp_Object glyph = sym;
223 /* if we have a symbol get at the actual data */
225 glyph = XSYMBOL (glyph)->value;
228 glyph = Feval (glyph);
230 /* Be really helpful to the user. */
233 glyph = call1 (intern ("make-glyph"), glyph);
236 /* substitute the new glyph */
237 RETURN_UNGCPRO (glyph);
241 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val)
244 /* substitute the new glyph */
245 for (i = 0; i < XVECTOR_LENGTH (inst); i++)
247 if (EQ (key, XVECTOR_DATA (inst)[i]))
249 XVECTOR_DATA (inst)[i+1] = val;
255 /* Wire widget property invocations to specific widgets. The problem
256 we are solving here is that when instantiators get converted to
257 instances they lose some type information (they just become
258 subwindows or widgets for example). For widgets we need to preserve
259 this type information so that we can do widget specific operations
260 on the instances. This is encoded in the widget type
261 field. widget_property gets invoked by decoding the primary type
262 (Qwidget), <widget>_property then invokes based on the secondary
263 type (Qedit_field for example). It is debatable whether we should
264 wire things in this generalised way rather than treating widgets
265 specially in image_instance_property. */
267 widget_property (Lisp_Object image_instance, Lisp_Object prop)
269 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
270 struct image_instantiator_methods* meths;
272 /* first see if its a general property ... */
273 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
274 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
276 /* .. then try device specific methods ... */
277 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
278 IMAGE_INSTANCE_WIDGET_TYPE (ii),
280 if (meths && HAS_IIFORMAT_METH_P (meths, property))
281 return IIFORMAT_METH (meths, property, (image_instance, prop));
282 /* ... then format specific methods ... */
283 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
285 if (meths && HAS_IIFORMAT_METH_P (meths, property))
286 return IIFORMAT_METH (meths, property, (image_instance, prop));
292 widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
294 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
295 struct image_instantiator_methods* meths;
298 /* PIck up any generic properties that we might need to keep hold
300 if (EQ (prop, Q_text))
302 IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
303 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
306 /* Now try device specific methods first ... */
307 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
308 IMAGE_INSTANCE_WIDGET_TYPE (ii),
310 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
313 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
317 /* ... then format specific methods ... */
318 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
320 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
323 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
327 /* we didn't do any device specific properties, so shove the property in our plist */
328 IMAGE_INSTANCE_WIDGET_PROPS (ii)
329 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
333 /* Like the rest of redisplay, we want widget updates to occur
334 asynchronously. Thus toolkit specific methods for setting properties
335 must be called by redisplay instead of by *_set_property. Thus
336 *_set_property records the change and this function actually
337 implements it. We want to be slightly clever about this however by
338 supplying format specific functions for the updates instead of lumping
339 them all into this function. Note that there is no need for format
340 generic functions. */
342 update_widget (Lisp_Object widget)
344 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
345 struct image_instantiator_methods* meths;
347 if (IMAGE_INSTANCE_TYPE (ii) != IMAGE_WIDGET)
350 /* Device generic methods. We must update the widget's size as it
351 may have been changed by the the layout routines. We also do this
352 here so that explicit resizing from lisp does not result in
353 synchronous updates. */
354 MAYBE_DEVMETH (XDEVICE (ii->device), update_widget, (ii));
356 /* Device-format specific methods */
357 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
358 IMAGE_INSTANCE_WIDGET_TYPE (ii),
360 MAYBE_IIFORMAT_METH (meths, update, (widget));
362 /* Pick up the items we recorded earlier. */
363 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
365 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
366 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
367 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
371 /* Query for a widgets desired geometry. If no type specific method is
372 provided then use the widget text to calculate sizes. */
374 widget_query_geometry (Lisp_Object image_instance,
375 unsigned int* width, unsigned int* height,
376 enum image_instance_geometry disp, Lisp_Object domain)
378 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
379 struct image_instantiator_methods* meths;
380 Lisp_Object dynamic_width = Qnil;
381 Lisp_Object dynamic_height = Qnil;
383 /* First just set up what we already have. */
384 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
385 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
387 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
389 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
391 /* .. then try device specific methods ... */
392 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
393 IMAGE_INSTANCE_WIDGET_TYPE (ii),
395 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
396 IIFORMAT_METH (meths, query_geometry, (image_instance,
401 /* ... then format specific methods ... */
402 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
404 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
405 IIFORMAT_METH (meths, query_geometry, (image_instance,
412 /* Then if we are allowed to resize the widget, make the
413 size the same as the text dimensions. */
414 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
415 IMAGE_INSTANCE_WIDGET_FACE (ii),
417 /* Adjust the size for borders. */
418 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
419 *width = w + 2 * WIDGET_BORDER_WIDTH;
420 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
421 *height = h + 2 * WIDGET_BORDER_HEIGHT;
424 /* Finish off with dynamic sizing. */
425 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
427 dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
428 if (INTP (dynamic_width))
429 *width = XINT (dynamic_width);
431 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
433 dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
434 if (INTP (dynamic_height))
435 *height = XINT (dynamic_height);
441 widget_layout (Lisp_Object image_instance,
442 unsigned int width, unsigned int height, Lisp_Object domain)
444 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
445 struct image_instantiator_methods* meths;
447 /* .. then try device specific methods ... */
448 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
449 IMAGE_INSTANCE_WIDGET_TYPE (ii),
451 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
452 IIFORMAT_METH (meths, layout, (image_instance,
453 width, height, domain));
456 /* ... then format specific methods ... */
457 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
459 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
460 IIFORMAT_METH (meths, layout, (image_instance,
461 width, height, domain));
466 widget_validate (Lisp_Object instantiator)
468 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
471 signal_simple_error ("Must supply :descriptor", instantiator);
474 gui_parse_item_keywords (desc);
476 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
477 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
478 signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
480 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
481 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
482 signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
486 combo_box_validate (Lisp_Object instantiator)
488 widget_validate (instantiator);
489 if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
490 signal_simple_error ("Must supply item list", instantiator);
493 /* we need to convert things like glyphs to images, eval expressions
496 widget_normalize (Lisp_Object inst, Lisp_Object console_type)
498 /* This function can call lisp */
499 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
501 /* we need to eval glyph if its an expression, we do this for the
502 same reasons we normalize file to data. */
505 substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
512 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
514 /* initialize_subwindow_image_instance (ii);*/
515 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
516 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
517 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
518 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
519 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
520 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
521 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
522 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
523 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
524 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
525 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
528 /* Instantiate a button widget. Unfortunately instantiated widgets are
529 particular to a frame since they need to have a parent. It's not
530 like images where you just select the image into the context you
531 want to display it in and BitBlt it. So image instances can have a
532 many-to-one relationship with things you see, whereas widgets can
533 only be one-to-one (i.e. per frame) */
535 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
536 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
537 int dest_mask, Lisp_Object domain)
539 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
540 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
541 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
542 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
543 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
544 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
545 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
546 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
547 Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
548 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
549 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
550 int pw=0, ph=0, tw=0, th=0;
552 /* this just does pixel type sizing */
553 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
556 if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK)))
557 incompatible_image_types (instantiator, dest_mask,
558 IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
560 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
562 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
563 IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
565 /* retrieve the fg and bg colors */
567 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
569 /* Do layout specific initialisation. This feels a bit tacky, but
570 the alternative is a myriad of different little functions. */
571 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
573 Lisp_Object rest, children = Qnil;
574 Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
578 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
580 IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
584 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
586 else if (GLYPHP (border))
588 /* We are going to be sneaky here and add the border text as
589 just another child, the layout and output routines don't know
590 this and will just display at the offsets we prescribe. */
591 Lisp_Object gii = glyph_image_instance (border, domain, ERROR_ME, 1);
592 /* make sure we are designated as the parent. */
593 XIMAGE_INSTANCE_PARENT (gii) = image_instance;
594 children = Fcons (gii, children);
595 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
599 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
602 /* Pick up the sub-widgets. */
603 LIST_LOOP (rest, items)
605 /* make sure the image is instantiated */
606 Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
607 /* make sure we are designated as the parent. */
608 XIMAGE_INSTANCE_PARENT (gii) = image_instance;
609 children = Fcons (gii, children);
611 /* Make sure elements in the layout are in the order the
613 children = Fnreverse (children);
614 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
616 /* retrieve the gui item information. This is easy if we have been
617 provided with a vector, more difficult if we have just been given
619 else if (STRINGP (desc) || NILP (desc))
621 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
622 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
623 gui_parse_item_keywords_no_errors (instantiator);
624 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
627 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
628 gui_parse_item_keywords_no_errors (desc);
630 /* Pick up the orientation before we do our first layout. */
631 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
632 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
634 /* parse more gui items out of the properties */
636 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
640 items = Fplist_get (props, Q_items, Qnil);
644 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
645 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
646 parse_gui_item_tree_children (items));
650 /* Normalize size information. We now only assign sizes if the user
651 gives us some explicitly, or there are some constraints that we
652 can't change later on. Otherwise we postpone sizing until query
653 geometry gets called. */
654 if (!NILP (pixwidth)) /* pixwidth takes precendent */
656 if (!INTP (pixwidth))
657 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth;
660 pw = XINT (pixwidth);
661 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
664 else if (!NILP (width))
667 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
670 if (!NILP (pixheight))
672 if (!INTP (pixheight))
673 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight;
676 ph = XINT (pixheight);
677 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
680 else if (!NILP (height) && XINT (height) > 1)
683 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
686 /* Taking the default face information when the user has specified
687 size in characters is probably as good as any since the widget
688 face is more likely to be proportional and thus give inadequate
689 results. Using character sizes can only ever be approximate
693 int charwidth, charheight;
694 default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
698 ph = charheight * th;
701 /* for a widget with an image pick up the dimensions from that */
705 pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH;
707 ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT;
708 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
709 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
712 /* When we create the widgets the window system expects a valid
713 size, so If we still don' t have sizes, call layout to pick them
714 up. If query_geometry or layout relies on the widget being in
715 existence then we are in catch 22. */
716 image_instance_layout (image_instance,
717 pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
718 ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
722 debug_widget_instances++;
723 stderr_out ("instantiated ");
724 debug_print (instantiator);
725 stderr_out ("%d widgets instantiated\n", debug_widget_instances);
729 /* Get the geometry of a button control. We need to adjust the size
730 depending on the type of button. */
732 button_query_geometry (Lisp_Object image_instance,
733 unsigned int* width, unsigned int* height,
734 enum image_instance_geometry disp, Lisp_Object domain)
736 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
738 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
739 IMAGE_INSTANCE_WIDGET_FACE (ii),
741 /* Adjust the size for borders. */
742 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
744 *width = w + 2 * WIDGET_BORDER_WIDTH;
746 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
748 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
749 /* This is an approximation to the size of the actual button bit. */
752 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
753 *height = h + 2 * WIDGET_BORDER_HEIGHT;
756 /* tree-view geometry - get the height right */
758 tree_view_query_geometry (Lisp_Object image_instance,
759 unsigned int* width, unsigned int* height,
760 enum image_instance_geometry disp, Lisp_Object domain)
762 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
763 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
768 /* #### what should this be. reconsider when X has tree views. */
769 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
770 IMAGE_INSTANCE_WIDGET_FACE (ii),
771 width, 0, 0, domain);
776 default_face_font_info (domain, 0, 0, &h, 0, 0);
777 GET_LIST_LENGTH (items, len);
782 /* Get the geometry of a tab control. This is based on the number of
783 items and text therin in the tab control. */
785 tab_control_query_geometry (Lisp_Object image_instance,
786 unsigned int* width, unsigned int* height,
787 enum image_instance_geometry disp, Lisp_Object domain)
789 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
790 Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
792 unsigned int tw = 0, th = 0;
794 LIST_LOOP (rest, items)
798 query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
799 IMAGE_INSTANCE_WIDGET_FACE (ii),
801 tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
803 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
806 /* Fixup returned values depending on orientation. */
807 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
809 if (height) *height = tw;
810 if (width) *width = th;
814 if (height) *height = th;
815 if (width) *width = tw;
819 /* Get the geometry of a tab control. This is based on the number of
820 items and text therin in the tab control. */
822 tab_control_set_property (Lisp_Object image_instance,
826 /* Record new items for update. *_tab_control_update will do the
828 if (EQ (prop, Q_items))
830 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
832 check_valid_item_list_1 (val);
834 /* Don't set the actual items since we might decide not to use
835 the new ones (because nothing has really changed). If we did
836 set them and didn't use them then we would get into whole
837 heaps of trouble when the old items get GC'd. */
838 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
839 Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
840 parse_gui_item_tree_children (val));
841 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
848 /* set the properties of a progres guage */
850 progress_gauge_set_property (Lisp_Object image_instance,
854 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
856 if (EQ (prop, Q_value))
859 #ifdef DEBUG_WIDGET_OUTPUT
860 printf ("progress gauge value set to %ld\n", XINT (val));
862 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
863 copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
864 #ifdef ERROR_CHECK_GLYPHS
865 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
867 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
868 XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = val;
870 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
878 /*****************************************************************************
880 *****************************************************************************/
882 layout_possible_dest_types (void)
884 return IMAGE_LAYOUT_MASK;
887 /* we need to convert things like glyphs to images, eval expressions
890 layout_normalize (Lisp_Object inst, Lisp_Object console_type)
892 /* This function can call lisp */
893 Lisp_Object items = find_keyword_in_vector (inst, Q_items);
894 Lisp_Object border = find_keyword_in_vector (inst, Q_border);
895 /* we need to eval glyph if its an expression, we do this for the
896 same reasons we normalize file to data. */
900 LIST_LOOP (rest, items)
902 /* substitute the new glyph */
903 Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest)));
906 /* normalize the border spec. */
907 if (VECTORP (border) || CONSP (border))
909 substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border));
914 /* Layout widget. Sizing commentary: we have a number of problems that
915 we would like to address. Some consider some of these more
916 important than others. It used to be that size information was
917 determined at instantiation time and was then fixed forever
918 after. Generally this is not what we want. Users want size to be
919 "big enough" to accommodate whatever they are trying to show and
920 this is dependent on text length, lines, font metrics etc. Of
921 course these attributes can change dynamically and so the size
922 should changed dynamically also. Only in a few limited cases should
923 the size be fixed and remain fixed. Of course this actually means
924 that we don't really want to specifiy the size *at all* for most
925 widgets - we want it to be discovered dynamically. Thus we can
926 envisage the following scenarios:
928 1. A button is sized to accommodate its text, the text changes and the
929 button should change size also.
931 2. A button is given an explicit size. Its size should never change.
933 3. Layout is put inside an area. The size of the area changes, the
934 layout should change with it.
936 4. A button grows to accommodate additional text. The whitespace
937 around it should be modified to cope with the new layout
940 5. A button grows. The area surrounding it should grow also if
943 What metrics are important?
944 1. Actual width and height.
946 2. Whether the width and height are what the widget actually wants, or
947 whether it can grow or shrink.
949 Text glyphs are particularly troublesome since their metrics depend
950 on the context in which they are being viewed. For instance they
951 can appear differently depending on the window face, frame face or
952 glyph face. In order to simplify this text glyphs can now only have
953 a glyph-face or image-instance face. All other glyphs are
954 essentially fixed in appearance. Perhaps the problem is that text
955 glyphs are cached on a device basis like most other glyphs. Instead
956 they should be cached per-window and then the instance would be
957 fixed and we wouldn't have to mess around with font metrics and the
960 /* Query the geometry of a layout widget. We assume that we can only
961 get here if the size is not already fixed. */
963 layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
964 unsigned int* height, enum image_instance_geometry disp,
967 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
968 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
969 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
970 unsigned int gheight, gwidth;
972 /* First just set up what we already have. */
973 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
974 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
976 /* If we are not allowed to dynamically size then return. */
977 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
979 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
982 /* Pick up the border text if we have one. */
983 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
985 image_instance_query_geometry (XCAR (items), &gwidth, &gheight, disp, domain);
986 ph_adjust = gheight / 2;
987 items = XCDR (items);
990 /* Flip through the items to work out how much stuff we have to display */
991 LIST_LOOP (rest, items)
993 Lisp_Object glyph = XCAR (rest);
994 image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain);
997 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
998 == LAYOUT_HORIZONTAL)
1000 maxph = max (maxph, gheight);
1005 maxpw = max (maxpw, gwidth);
1010 /* Work out minimum space we need to fit all the items. This could
1011 have been fixed by the user. */
1012 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
1014 Lisp_Object dynamic_width =
1015 Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
1016 if (INTP (dynamic_width))
1017 *width = XINT (dynamic_width);
1019 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1020 == LAYOUT_HORIZONTAL)
1021 *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2;
1023 *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
1025 /* Work out vertical spacings. */
1026 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
1028 Lisp_Object dynamic_height =
1029 Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
1030 if (INTP (dynamic_height))
1031 *height = XINT (dynamic_height);
1033 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1035 *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
1037 *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
1041 layout_layout (Lisp_Object image_instance,
1042 unsigned int width, unsigned int height, Lisp_Object domain)
1044 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1046 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
1047 int x, y, maxph = 0, maxpw = 0, nitems = 0,
1048 horiz_spacing, vert_spacing, ph_adjust = 0;
1049 unsigned int gheight, gwidth;
1051 /* Pick up the border text if we have one. */
1052 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1054 Lisp_Object border = XCAR (items);
1055 items = XCDR (items);
1056 image_instance_query_geometry (border, &gwidth, &gheight,
1057 IMAGE_DESIRED_GEOMETRY, domain);
1058 /* #### Really, what should this be? */
1059 XIMAGE_INSTANCE_XOFFSET (border) = 10;
1060 XIMAGE_INSTANCE_YOFFSET (border) = 0;
1061 ph_adjust = gheight / 2;
1062 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
1064 image_instance_layout (border, gwidth, gheight, domain);
1067 /* Flip through the items to work out how much stuff we have to display. */
1068 LIST_LOOP (rest, items)
1070 Lisp_Object glyph = XCAR (rest);
1072 image_instance_query_geometry (glyph, &gwidth, &gheight,
1073 IMAGE_DESIRED_GEOMETRY, domain);
1075 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1076 == LAYOUT_HORIZONTAL)
1078 maxph = max (maxph, gheight);
1083 maxpw = max (maxpw, gwidth);
1088 /* work out spacing between items and bounds of the layout */
1090 /* The user wants a smaller space than the largest item, so we
1091 just provide default spacing and will let the output routines
1093 horiz_spacing = WIDGET_BORDER_WIDTH * 2;
1094 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1095 == LAYOUT_HORIZONTAL)
1096 /* We have a larger area to display in so distribute the space
1098 horiz_spacing = (width - maxpw) / (nitems + 1);
1100 horiz_spacing = (width - maxpw) / 2;
1103 vert_spacing = WIDGET_BORDER_HEIGHT * 2;
1104 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1106 vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1);
1108 vert_spacing = (height - (maxph + ph_adjust)) / 2;
1110 y = vert_spacing + ph_adjust;
1113 /* Now flip through putting items where we want them, paying
1114 attention to justification. Make sure we don't mess with the
1116 LIST_LOOP (rest, items)
1118 Lisp_Object glyph = XCAR (rest);
1120 image_instance_query_geometry (glyph, &gwidth, &gheight,
1121 IMAGE_DESIRED_GEOMETRY, domain);
1123 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1124 == LAYOUT_HORIZONTAL)
1126 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1127 == LAYOUT_JUSTIFY_RIGHT)
1128 y = height - (gheight + vert_spacing);
1129 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1130 == LAYOUT_JUSTIFY_CENTER)
1131 y = (height - gheight) / 2;
1135 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1136 == LAYOUT_JUSTIFY_RIGHT)
1137 x = width - (gwidth + horiz_spacing);
1138 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1139 == LAYOUT_JUSTIFY_CENTER)
1140 x = (width - gwidth) / 2;
1143 XIMAGE_INSTANCE_XOFFSET (glyph) = x;
1144 XIMAGE_INSTANCE_YOFFSET (glyph) = y;
1146 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1147 == LAYOUT_HORIZONTAL)
1149 x += (gwidth + horiz_spacing);
1153 y += (gheight + vert_spacing);
1156 /* Now layout subwidgets if they require it. */
1157 image_instance_layout (glyph, gwidth, gheight, domain);
1162 /************************************************************************/
1163 /* initialization */
1164 /************************************************************************/
1167 syms_of_glyphs_widget (void)
1169 defkeyword (&Q_descriptor, ":descriptor");
1170 defkeyword (&Q_height, ":height");
1171 defkeyword (&Q_width, ":width");
1172 defkeyword (&Q_properties, ":properties");
1173 defkeyword (&Q_items, ":items");
1174 defkeyword (&Q_image, ":image");
1175 defkeyword (&Q_text, ":text");
1176 defkeyword (&Q_orientation, ":orientation");
1177 defkeyword (&Q_justify, ":justify");
1178 defkeyword (&Q_border, ":border");
1180 defsymbol (&Qetched_in, "etched-in");
1181 defsymbol (&Qetched_out, "etched-out");
1182 defsymbol (&Qbevel_in, "bevel-in");
1183 defsymbol (&Qbevel_out, "bevel-out");
1184 defsymbol (&Qwidget_callback_current_channel, "widget-callback-current-channel");
1187 #define VALID_GUI_KEYWORDS(type) do { \
1188 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \
1189 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
1190 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
1191 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
1192 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \
1193 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
1194 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
1195 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
1196 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
1197 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
1198 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
1199 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \
1200 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \
1201 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector); \
1204 #define VALID_WIDGET_KEYWORDS(type) do { \
1205 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
1206 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
1207 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function);\
1208 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function);\
1209 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \
1213 static void image_instantiator_widget (void)
1214 { /* we only do this for properties */
1215 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1216 IIFORMAT_HAS_METHOD (widget, property);
1217 IIFORMAT_HAS_METHOD (widget, set_property);
1218 IIFORMAT_HAS_METHOD (widget, query_geometry);
1219 IIFORMAT_HAS_METHOD (widget, layout);
1222 static void image_instantiator_buttons (void)
1224 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1225 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1226 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1227 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1228 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1229 IIFORMAT_HAS_METHOD (button, query_geometry);
1230 IIFORMAT_VALID_KEYWORD (button,
1231 Q_image, check_valid_glyph_or_instantiator);
1232 VALID_WIDGET_KEYWORDS (button);
1233 VALID_GUI_KEYWORDS (button);
1236 static void image_instantiator_edit_fields (void)
1238 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1239 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1240 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1241 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1242 VALID_WIDGET_KEYWORDS (edit_field);
1243 VALID_GUI_KEYWORDS (edit_field);
1246 static void image_instantiator_combo_box (void)
1248 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1249 IIFORMAT_HAS_METHOD (combo_box, validate);
1250 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1251 VALID_GUI_KEYWORDS (combo_box);
1253 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1254 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1255 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int_or_function);
1256 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1257 IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list);
1260 static void image_instantiator_scrollbar (void)
1262 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1263 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1264 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1265 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1266 VALID_GUI_KEYWORDS (scrollbar);
1268 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int_or_function);
1269 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int_or_function);
1270 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1273 static void image_instantiator_progress_guage (void)
1275 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1276 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1277 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1278 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1279 IIFORMAT_HAS_METHOD (progress_gauge, set_property);
1280 VALID_WIDGET_KEYWORDS (progress_gauge);
1281 VALID_GUI_KEYWORDS (progress_gauge);
1284 static void image_instantiator_tree_view (void)
1286 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1287 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1288 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1289 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1290 IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1291 VALID_WIDGET_KEYWORDS (tree_view);
1292 VALID_GUI_KEYWORDS (tree_view);
1293 IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
1296 static void image_instantiator_tab_control (void)
1298 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1299 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1300 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1301 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1302 IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1303 IIFORMAT_HAS_METHOD (tab_control, set_property);
1304 VALID_WIDGET_KEYWORDS (tab_control);
1305 VALID_GUI_KEYWORDS (tab_control);
1306 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
1307 IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
1310 static void image_instantiator_labels (void)
1312 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1313 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1314 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1315 VALID_WIDGET_KEYWORDS (label);
1316 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1319 static void image_instantiator_layout (void)
1321 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1322 IIFORMAT_HAS_METHOD (layout, possible_dest_types);
1323 IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget);
1324 IIFORMAT_HAS_METHOD (layout, normalize);
1325 IIFORMAT_HAS_METHOD (layout, query_geometry);
1326 IIFORMAT_HAS_METHOD (layout, layout);
1327 VALID_WIDGET_KEYWORDS (layout);
1328 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);
1329 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);
1330 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);
1331 IIFORMAT_VALID_KEYWORD (layout, Q_items,
1332 check_valid_glyph_or_instantiator_list);
1336 image_instantiator_format_create_glyphs_widget (void)
1338 image_instantiator_widget();
1339 image_instantiator_buttons();
1340 image_instantiator_edit_fields();
1341 image_instantiator_combo_box();
1342 image_instantiator_scrollbar();
1343 image_instantiator_progress_guage();
1344 image_instantiator_tree_view();
1345 image_instantiator_tab_control();
1346 image_instantiator_labels();
1347 image_instantiator_layout();
1351 reinit_vars_of_glyphs_widget (void)
1353 #ifdef DEBUG_WIDGETS
1354 debug_widget_instances = 0;
1359 vars_of_glyphs_widget (void)
1361 reinit_vars_of_glyphs_widget ();
1363 DEFVAR_LISP ("widget-callback-current-channel", &Vwidget_callback_current_channel /*
1364 The domain that is current when a widget callback is invoked.
1365 This is invariably the frame that the widget is instantiated in.
1367 Vwidget_callback_current_channel = Qnil;