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))
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;
298 Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
299 /* Pick up any generic properties that we might need to keep hold
303 IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
304 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
307 /* Now try device specific methods first ... */
308 meths = decode_device_ii_format (image_instance_device (image_instance),
309 IMAGE_INSTANCE_WIDGET_TYPE (ii),
311 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
312 /* ... then format specific methods ... */
313 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
315 MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
316 #if 0 /* The usefulness of this is dubious. */
317 /* we didn't do any device specific properties, so shove the property in our plist. */
318 IMAGE_INSTANCE_WIDGET_PROPS (ii)
319 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
323 /* Like the rest of redisplay, we want widget updates to occur
324 asynchronously. Thus toolkit specific methods for setting
325 properties must be called by redisplay instead of by *_update. Thus
326 *_update records the change and this function actually implements
327 it. We want to be slightly clever about this however by supplying
328 format specific functions for the updates instead of lumping them
329 all into this function. Note that there is no need for format
330 generic functions. This is not the same as widget_update! */
332 redisplay_widget (Lisp_Object widget)
334 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
335 struct image_instantiator_methods* meths;
337 if (!WIDGET_IMAGE_INSTANCEP (widget)
338 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
339 || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
342 /* Device-format specific methods - e.g. x_tab_control_redisplay () */
343 meths = decode_device_ii_format (image_instance_device (widget),
344 IMAGE_INSTANCE_WIDGET_TYPE (ii),
346 MAYBE_IIFORMAT_METH (meths, redisplay, (widget));
348 /* Device generic methods - e.g. x_redisplay_widget (). We must
349 update the widget's size as it may have been changed by the the
350 layout routines. We also do this here so that explicit resizing
351 from lisp does not result in synchronous updates. Do this last so
352 that format-specific methods have an opportunity to prevent
353 wholesale changes - e.g. rebuilding tabs. */
354 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii));
356 /* Pick up the items we recorded earlier. */
357 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
359 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
360 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
361 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
365 /* Query for a widgets desired geometry. If no type specific method is
366 provided then use the widget text to calculate sizes. */
368 widget_query_geometry (Lisp_Object image_instance,
369 int* width, int* height,
370 enum image_instance_geometry disp, Lisp_Object domain)
372 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
373 struct image_instantiator_methods* meths;
374 Lisp_Object dynamic_width = Qnil;
375 Lisp_Object dynamic_height = Qnil;
377 /* First just set up what we already have. */
378 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
379 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
381 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
383 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
385 /* .. then try device specific methods ... */
386 meths = decode_device_ii_format (image_instance_device (image_instance),
387 IMAGE_INSTANCE_WIDGET_TYPE (ii),
389 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
390 IIFORMAT_METH (meths, query_geometry, (image_instance,
395 /* ... then format specific methods ... */
396 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
398 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
399 IIFORMAT_METH (meths, query_geometry, (image_instance,
406 /* Then if we are allowed to resize the widget, make the
407 size the same as the text dimensions. */
408 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
409 IMAGE_INSTANCE_WIDGET_FACE (ii),
411 /* Adjust the size for borders. */
412 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
413 *width = w + 2 * WIDGET_BORDER_WIDTH;
414 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
415 *height = h + 2 * WIDGET_BORDER_HEIGHT;
418 /* Finish off with dynamic sizing. */
419 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
421 dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
422 if (INTP (dynamic_width))
423 *width = XINT (dynamic_width);
425 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
427 dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
428 if (INTP (dynamic_height))
429 *height = XINT (dynamic_height);
435 widget_layout (Lisp_Object image_instance,
436 int width, int height, int xoffset, int yoffset,
439 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
440 struct image_instantiator_methods* meths;
442 /* .. then try device specific methods ... */
443 meths = decode_device_ii_format (image_instance_device (image_instance),
444 IMAGE_INSTANCE_WIDGET_TYPE (ii),
446 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
447 return IIFORMAT_METH (meths, layout, (image_instance,
448 width, height, xoffset, yoffset,
452 /* ... then format specific methods ... */
453 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
455 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
456 return IIFORMAT_METH (meths, layout, (image_instance,
457 width, height, xoffset, yoffset,
464 widget_validate (Lisp_Object instantiator)
466 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
469 syntax_error ("Must supply :descriptor", instantiator);
472 gui_parse_item_keywords (desc);
474 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
475 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
476 syntax_error ("Must supply only one of :width and :pixel-width", instantiator);
478 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
479 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
480 syntax_error ("Must supply only one of :height and :pixel-height", instantiator);
484 combo_box_validate (Lisp_Object instantiator)
486 widget_validate (instantiator);
487 if (NILP (find_keyword_in_vector (instantiator, Q_items)))
488 syntax_error ("Must supply item list", instantiator);
491 /* we need to convert things like glyphs to images, eval expressions
494 widget_normalize (Lisp_Object inst, Lisp_Object console_type,
495 Lisp_Object dest_mask)
497 /* This function can call lisp */
498 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
500 /* we need to eval glyph if its an expression, we do this for the
501 same reasons we normalize file to data.
503 #### should just normalize the data. */
506 substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
513 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
515 /* initialize_subwindow_image_instance (ii);*/
516 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
517 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
518 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
519 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
520 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil;
521 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
522 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
523 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
524 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
525 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
526 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
527 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
530 /* Instantiate a button widget. Unfortunately instantiated widgets are
531 particular to a frame since they need to have a parent. It's not
532 like images where you just select the image into the context you
533 want to display it in and BitBlt it. So image instances can have a
534 many-to-one relationship with things you see, whereas widgets can
535 only be one-to-one (i.e. per frame) */
537 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
538 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
539 int dest_mask, Lisp_Object domain)
541 /* #### practically all of this should be moved to widget_update()
542 so that users can dynamically change all possible widget
544 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
545 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
546 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
547 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
548 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
549 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
550 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
551 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
552 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
553 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
554 Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width);
555 Lisp_Object ifocus = find_keyword_in_vector (instantiator, Q_initial_focus);
556 int pw=0, ph=0, tw=0, th=0;
558 /* this just does pixel type sizing */
559 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
562 if (!(dest_mask & IMAGE_WIDGET_MASK))
563 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
565 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
567 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
569 /* retrieve the fg and bg colors */
571 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
573 /* retrieve the gui item information. This is easy if we have been
574 provided with a vector, more difficult if we have just been given
576 if (STRINGP (desc) || NILP (desc))
578 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
579 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
580 gui_parse_item_keywords_no_errors (instantiator);
581 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
584 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
585 gui_parse_item_keywords_no_errors (desc);
587 /* Pick up the orientation before we do our first layout. */
588 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
589 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
591 /* parse more gui items out of the properties */
592 if (!NILP (items) && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
593 && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
595 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
596 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
597 parse_gui_item_tree_children (items));
600 /* Normalize size information. We now only assign sizes if the user
601 gives us some explicitly, or there are some constraints that we
602 can't change later on. Otherwise we postpone sizing until query
603 geometry gets called. */
604 if (!NILP (pixwidth)) /* pixwidth takes precendent */
606 if (!INTP (pixwidth))
607 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth;
610 pw = XINT (pixwidth);
611 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
614 else if (!NILP (width))
617 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
620 if (!NILP (pixheight))
622 if (!INTP (pixheight))
623 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight;
626 ph = XINT (pixheight);
627 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
630 else if (!NILP (height) && XINT (height) > 1)
633 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
636 /* Taking the default face information when the user has specified
637 size in characters is probably as good as any since the widget
638 face is more likely to be proportional and thus give inadequate
639 results. Using character sizes can only ever be approximate
643 int charwidth, charheight;
644 default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
648 ph = charheight * th;
651 /* for a widget with an image pick up the dimensions from that */
655 pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH;
657 ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT;
658 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
659 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
662 /* Pick up the margin width. */
664 IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth);
666 IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (ii) = !NILP (ifocus);
668 /* Layout for the layout widget is premature at this point since the
669 children will not have been instantiated. We can't instantiate
670 them until the device instantiation method for the layout has
671 been executed. We do however want to record any specified
673 if (pw) IMAGE_INSTANCE_WIDTH (ii) = pw;
674 if (ph) IMAGE_INSTANCE_HEIGHT (ii) = ph;
678 widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
682 debug_widget_instances++;
683 stderr_out ("instantiated ");
684 debug_print (instantiator);
685 stderr_out ("%d widgets instantiated\n", debug_widget_instances);
689 /* Get the geometry of a button control. We need to adjust the size
690 depending on the type of button. */
692 button_query_geometry (Lisp_Object image_instance,
693 int* width, int* height,
694 enum image_instance_geometry disp, Lisp_Object domain)
696 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
698 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
699 IMAGE_INSTANCE_WIDGET_FACE (ii),
701 /* Adjust the size for borders. */
702 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
704 *width = w + 2 * WIDGET_BORDER_WIDTH;
706 if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
708 EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
709 /* This is an approximation to the size of the actual button bit. */
712 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
713 *height = h + 2 * WIDGET_BORDER_HEIGHT;
716 /* tree-view geometry - get the height right */
718 tree_view_query_geometry (Lisp_Object image_instance,
719 int* width, int* height,
720 enum image_instance_geometry disp, Lisp_Object domain)
722 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
723 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
728 /* #### what should this be. reconsider when X has tree views. */
729 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
730 IMAGE_INSTANCE_WIDGET_FACE (ii),
731 width, 0, 0, domain);
736 default_face_font_info (domain, 0, 0, &h, 0, 0);
737 GET_LIST_LENGTH (items, len);
742 /* Get the geometry of a tab control. This is based on the number of
743 items and text therin in the tab control. */
745 tab_control_query_geometry (Lisp_Object image_instance,
746 int* width, int* height,
747 enum image_instance_geometry disp, Lisp_Object domain)
749 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
750 Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
754 LIST_LOOP (rest, items)
758 query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
759 IMAGE_INSTANCE_WIDGET_FACE (ii),
761 tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
763 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
766 /* Fixup returned values depending on orientation. */
767 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
769 if (height) *height = tw;
770 if (width) *width = th;
774 if (height) *height = th;
775 if (width) *width = tw;
779 /* Update the contents of a tab control. */
781 tab_control_update (Lisp_Object image_instance,
782 Lisp_Object instantiator)
784 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
785 /* Record new items for update. *_tab_control_redisplay will do the
789 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
790 check_valid_item_list (items);
791 #ifdef DEBUG_WIDGET_OUTPUT
792 stderr_out ("tab control %p updated\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
794 /* Don't set the actual items since we might decide not to use
795 the new ones (because nothing has really changed). If we did
796 set them and didn't use them then we would get into whole
797 heaps of trouble when the old items get GC'd. */
798 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
799 Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
800 parse_gui_item_tree_children (items));
801 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
805 /* Determine whether only the order has changed for a tab. */
806 int tab_control_order_only_changed (Lisp_Object image_instance)
808 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
809 int found = 0, len, pending_len;
812 /* Degenerate case. */
813 if (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
816 /* See whether we just need a change in order. */
817 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_ITEMS (ii), len);
818 GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii),
820 if (len == pending_len)
822 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
824 Lisp_Object pending_rest;
826 LIST_LOOP (pending_rest,
827 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
829 if (gui_item_equal_sans_selected (XCAR (rest),
830 XCAR (pending_rest), 0))
843 /* Set the properties of a progress gauge */
845 progress_gauge_update (Lisp_Object image_instance,
846 Lisp_Object instantiator)
848 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
849 Lisp_Object value = find_keyword_in_vector (instantiator, Q_value);
854 #ifdef DEBUG_WIDGET_OUTPUT
855 stderr_out ("progress gauge value set to %ld\n", XINT (value));
857 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
858 copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
859 #ifdef ERROR_CHECK_GLYPHS
860 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
862 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
863 XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = value;
865 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
870 /*****************************************************************************
872 *****************************************************************************/
873 /* We need to cascade normalization.*/
875 layout_normalize (Lisp_Object inst, Lisp_Object console_type,
876 Lisp_Object dest_mask)
878 /* This function can call lisp */
879 struct gcpro gcpro1, gcpro2;
880 Lisp_Object alist = Qnil, new_items = Qnil, border;
881 /* This function can call lisp */
884 GCPRO2 (alist, new_items);
885 alist = tagged_vector_to_alist (inst);
886 items = assq_no_quit (Q_items, alist);
888 /* We need to normalize sub-objects. */
892 LIST_LOOP (rest, XCDR (items))
894 /* Substitute the new instantiator */
895 new_items = Fcons (normalize_image_instantiator (XCAR (rest),
896 console_type, dest_mask),
899 new_items = Fnreverse (new_items);
900 Fsetcdr (items, new_items);
902 /* Normalize the border spec. */
903 border = assq_no_quit (Q_border, alist);
904 if (!NILP (border) && VECTORP (XCDR (border)))
906 Fsetcdr (border, normalize_image_instantiator (XCDR (border),
907 console_type, dest_mask));
911 Lisp_Object result = alist_to_tagged_vector (XVECTOR_DATA (inst)[0],
914 RETURN_UNGCPRO (result);
918 /* Update the instances in the layout. */
920 layout_update (Lisp_Object image_instance, Lisp_Object instantiator)
922 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
923 Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
924 Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border);
925 Lisp_Object border = Qnil;
926 Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
927 int structure_changed = 0;
930 /* We want to avoid consing if we can. This is quite awkward because
931 we have to deal with the border as well as the items. */
935 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
937 border = XCAR (children);
938 children = XCDR (children);
941 #ifdef DEBUG_WIDGET_OUTPUT
942 stderr_out ("layout updated\n");
944 /* Update the border. */
945 if (!NILP (border_inst))
947 if (VECTORP (border_inst))
949 /* We are going to be sneaky here and add the border text as
950 just another child, the layout and output routines don't know
951 this and will just display at the offsets we prescribe. */
953 call3 (Qset_glyph_image, border, border_inst,
954 IMAGE_INSTANCE_DOMAIN (ii));
957 border = Fcons (call1 (Qmake_glyph, border_inst), Qnil);
958 structure_changed = 1;
960 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
967 structure_changed = 1;
969 if (EQ (border_inst, Qt))
970 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
972 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border_inst;
976 /* Pick up the sub-widgets. */
980 GET_LIST_LENGTH (items, len1);
981 GET_LIST_LENGTH (children, len2);
982 /* The structure hasn't changed so just update the images. */
983 if (!structure_changed && len1 == len2)
985 /* Pick up the sub-widgets. */
986 for (; !NILP (children); children = XCDR (children), items = XCDR (items))
988 call3 (Qset_glyph_image, XCAR (children), XCAR (items),
989 IMAGE_INSTANCE_DOMAIN (ii));
992 /* The structure has changed so start over. */
995 /* Instantiate any new glyphs. */
996 for (; !NILP (items); items = XCDR (items))
998 border = Fcons (call1 (Qmake_glyph, XCAR (items)), border);
1000 IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Fnreverse (border);
1007 layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1008 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1009 int dest_mask, Lisp_Object domain)
1011 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1012 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
1014 #ifdef DEBUG_WIDGET_OUTPUT
1015 stderr_out ("layout instantiated\n");
1017 /* Do widget type instantiation first. */
1018 widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
1023 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
1026 /* Get child glyphs and finish instantiation. We can't do image
1027 instance children yet as we might not have a containing
1029 layout_update (image_instance, instantiator);
1033 layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1038 /* Layout widget. Sizing commentary: we have a number of problems that
1039 we would like to address. Some consider some of these more
1040 important than others. It used to be that size information was
1041 determined at instantiation time and was then fixed forever
1042 after. Generally this is not what we want. Users want size to be
1043 "big enough" to accommodate whatever they are trying to show and
1044 this is dependent on text length, lines, font metrics etc. Of
1045 course these attributes can change dynamically and so the size
1046 should changed dynamically also. Only in a few limited cases should
1047 the size be fixed and remain fixed. Of course this actually means
1048 that we don't really want to specify the size *at all* for most
1049 widgets - we want it to be discovered dynamically. Thus we can
1050 envisage the following scenarios:
1052 1. A button is sized to accommodate its text, the text changes and the
1053 button should change size also.
1055 2. A button is given an explicit size. Its size should never change.
1057 3. Layout is put inside an area. The size of the area changes, the
1058 layout should change with it.
1060 4. A button grows to accommodate additional text. The whitespace
1061 around it should be modified to cope with the new layout
1064 5. A button grows. The area surrounding it should grow also if
1067 What metrics are important?
1068 1. Actual width and height.
1070 2. Whether the width and height are what the widget actually wants, or
1071 whether it can grow or shrink.
1073 Text glyphs are particularly troublesome since their metrics depend
1074 on the context in which they are being viewed. For instance they
1075 can appear differently depending on the window face, frame face or
1076 glyph face. In order to simplify this text glyphs can now only have
1077 a glyph-face or image-instance face. All other glyphs are
1078 essentially fixed in appearance. Perhaps the problem is that text
1079 glyphs are cached on a device basis like most other glyphs. Instead
1080 they should be cached per-window and then the instance would be
1081 fixed and we wouldn't have to mess around with font metrics and the
1084 /* Query the geometry of a layout widget. We assume that we can only
1085 get here if the size is not already fixed. */
1087 layout_query_geometry (Lisp_Object image_instance, int* width,
1088 int* height, enum image_instance_geometry disp,
1091 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1092 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
1093 int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
1094 int gheight, gwidth;
1096 /* If we are not initialized then we won't have any children. */
1097 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1100 /* First just set up what we already have. */
1101 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
1102 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
1104 /* If we are not allowed to dynamically size then return. */
1105 if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
1107 !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
1110 /* Pick up the border text if we have one. */
1111 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1113 glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp,
1115 ph_adjust = gheight / 2;
1116 items = XCDR (items);
1119 /* Flip through the items to work out how much stuff we have to display */
1120 LIST_LOOP (rest, items)
1122 Lisp_Object glyph = XCAR (rest);
1123 glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance);
1126 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1127 == LAYOUT_HORIZONTAL)
1129 maxph = max (maxph, gheight);
1134 maxpw = max (maxpw, gwidth);
1139 /* Work out minimum space we need to fit all the items. This could
1140 have been fixed by the user. */
1141 if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
1143 Lisp_Object dynamic_width =
1144 Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
1145 if (INTP (dynamic_width))
1146 *width = XINT (dynamic_width);
1148 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1149 == LAYOUT_HORIZONTAL)
1150 *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH +
1151 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
1153 *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 +
1154 IMAGE_INSTANCE_MARGIN_WIDTH (ii));
1156 /* Work out vertical spacings. */
1157 if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
1159 Lisp_Object dynamic_height =
1160 Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
1161 if (INTP (dynamic_height))
1162 *height = XINT (dynamic_height);
1164 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1166 *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT +
1167 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1169 *height = maxph + (2 * WIDGET_BORDER_HEIGHT +
1170 IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
1174 layout_layout (Lisp_Object image_instance,
1175 int width, int height, int xoffset, int yoffset,
1178 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1180 Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
1181 int x, y, maxph = 0, maxpw = 0, nitems = 0,
1182 horiz_spacing, vert_spacing, ph_adjust = 0;
1183 int gheight, gwidth;
1185 /* If we are not initialized then we won't have any children. */
1186 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1189 /* Pick up the border text if we have one. */
1190 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
1192 Lisp_Object border = XCAR (items);
1193 items = XCDR (items);
1194 glyph_query_geometry (border, &gwidth, &gheight,
1195 IMAGE_DESIRED_GEOMETRY, image_instance);
1196 ph_adjust = gheight / 2;
1197 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
1199 /* #### Really, what should this be? */
1200 glyph_do_layout (border, gwidth, gheight, 10, 0,
1204 /* Flip through the items to work out how much stuff we have to display. */
1205 LIST_LOOP (rest, items)
1207 Lisp_Object glyph = XCAR (rest);
1209 glyph_query_geometry (glyph, &gwidth, &gheight,
1210 IMAGE_DESIRED_GEOMETRY, image_instance);
1212 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1213 == LAYOUT_HORIZONTAL)
1215 maxph = max (maxph, gheight);
1220 maxpw = max (maxpw, gwidth);
1225 /* work out spacing between items and bounds of the layout */
1227 /* The user wants a smaller space than the largest item, so we
1228 just provide default spacing and will let the output routines
1230 horiz_spacing = WIDGET_BORDER_WIDTH * 2;
1231 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1232 == LAYOUT_HORIZONTAL)
1233 /* We have a larger area to display in so distribute the space
1235 horiz_spacing = (width - (maxpw +
1236 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1239 horiz_spacing = (width - maxpw) / 2
1240 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1243 vert_spacing = WIDGET_BORDER_HEIGHT * 2;
1244 else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1246 vert_spacing = (height - (maxph + ph_adjust +
1247 IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
1250 vert_spacing = (height - (maxph + ph_adjust)) / 2
1251 - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1253 y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1254 x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
1256 /* Now flip through putting items where we want them, paying
1257 attention to justification. Make sure we don't mess with the
1259 LIST_LOOP (rest, items)
1261 Lisp_Object glyph = XCAR (rest);
1263 glyph_query_geometry (glyph, &gwidth, &gheight,
1264 IMAGE_DESIRED_GEOMETRY, image_instance);
1266 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1267 == LAYOUT_HORIZONTAL)
1269 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1270 == LAYOUT_JUSTIFY_RIGHT)
1271 y = height - (gheight + vert_spacing);
1272 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1273 == LAYOUT_JUSTIFY_CENTER)
1274 y = (height - gheight) / 2;
1278 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1279 == LAYOUT_JUSTIFY_RIGHT)
1280 x = width - (gwidth + horiz_spacing);
1281 if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
1282 == LAYOUT_JUSTIFY_CENTER)
1283 x = (width - gwidth) / 2;
1286 /* Now layout subwidgets if they require it. */
1287 glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance);
1289 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
1290 == LAYOUT_HORIZONTAL)
1292 x += (gwidth + horiz_spacing);
1296 y += (gheight + vert_spacing);
1303 /* Get the glyphs that comprise a layout. These are created internally
1304 and so are otherwise inaccessible to lisp. We need some way of getting
1305 properties from the widgets that comprise a layout and this is the
1306 simplest way of doing it.
1308 #### Eventually we should allow some more intelligent access to
1311 layout_property (Lisp_Object image_instance, Lisp_Object prop)
1313 /* This function can GC. */
1314 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1315 if (EQ (prop, Q_items))
1317 if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) &&
1318 CONSP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)))
1319 return Fcopy_sequence (XCDR
1320 (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)));
1322 return Fcopy_sequence (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii));
1327 /* Layout subwindows if they are real subwindows. */
1329 native_layout_layout (Lisp_Object image_instance,
1330 int width, int height, int xoffset, int yoffset,
1333 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1336 /* The first time this gets called, the layout will be only
1337 partially instantiated. The children get done in
1338 post_instantiate. */
1339 if (!IMAGE_INSTANCE_INITIALIZED (ii))
1342 /* Defining this overrides the default layout_layout so we first have to call that to get
1343 suitable instances and values set up. */
1344 layout_layout (image_instance, width, height, xoffset, yoffset, domain);
1346 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))
1348 struct display_glyph_area dga;
1351 dga.width = IMAGE_INSTANCE_WIDTH (ii);
1352 dga.height = IMAGE_INSTANCE_HEIGHT (ii);
1354 map_subwindow (XCAR (rest),
1355 IMAGE_INSTANCE_XOFFSET (ii),
1356 IMAGE_INSTANCE_YOFFSET (ii), &dga);
1362 /************************************************************************/
1363 /* initialization */
1364 /************************************************************************/
1367 syms_of_glyphs_widget (void)
1369 DEFSYMBOL (Qetched_in);
1370 DEFSYMBOL (Qetched_out);
1371 DEFSYMBOL (Qbevel_in);
1372 DEFSYMBOL (Qbevel_out);
1373 DEFSYMBOL (Qmake_glyph);
1376 #define VALID_GUI_KEYWORDS(type) do { \
1377 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything); \
1378 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
1379 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
1380 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
1381 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything); \
1382 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
1383 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
1384 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
1385 IIFORMAT_VALID_KEYWORD (type, Q_initial_focus, check_valid_anything); \
1386 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
1387 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
1388 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
1389 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \
1390 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \
1391 IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, \
1392 check_valid_string_or_vector); \
1395 #define VALID_WIDGET_KEYWORDS(type) do { \
1396 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
1397 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
1398 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function); \
1399 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function); \
1400 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \
1404 static void image_instantiator_widget (void)
1405 { /* we only do this for properties */
1406 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1407 IIFORMAT_HAS_METHOD (widget, property);
1408 IIFORMAT_HAS_METHOD (widget, update);
1409 IIFORMAT_HAS_METHOD (widget, query_geometry);
1410 IIFORMAT_HAS_METHOD (widget, layout);
1413 static void image_instantiator_buttons (void)
1415 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1416 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1417 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1418 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1419 IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget);
1420 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1421 IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow);
1422 IIFORMAT_HAS_METHOD (button, query_geometry);
1423 IIFORMAT_VALID_KEYWORD (button,
1424 Q_image, check_valid_instantiator);
1425 VALID_WIDGET_KEYWORDS (button);
1426 VALID_GUI_KEYWORDS (button);
1429 static void image_instantiator_edit_fields (void)
1431 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1432 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1433 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1434 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1435 IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
1436 IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
1437 VALID_WIDGET_KEYWORDS (edit_field);
1438 VALID_GUI_KEYWORDS (edit_field);
1441 static void image_instantiator_combo_box (void)
1443 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1444 IIFORMAT_HAS_METHOD (combo_box, validate);
1445 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1446 IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow);
1448 VALID_GUI_KEYWORDS (combo_box);
1450 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1451 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1452 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width,
1453 check_valid_int_or_function);
1454 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1455 IIFORMAT_VALID_KEYWORD (combo_box, Q_items, check_valid_item_list);
1458 static void image_instantiator_scrollbar (void)
1460 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1461 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1462 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1463 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1464 IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget);
1465 IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow);
1466 VALID_GUI_KEYWORDS (scrollbar);
1468 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width,
1469 check_valid_int_or_function);
1470 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height,
1471 check_valid_int_or_function);
1472 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1475 static void image_instantiator_progress_guage (void)
1477 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1478 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1479 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1480 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1481 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
1482 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
1483 IIFORMAT_HAS_METHOD (progress_gauge, update);
1484 VALID_WIDGET_KEYWORDS (progress_gauge);
1485 VALID_GUI_KEYWORDS (progress_gauge);
1487 IIFORMAT_VALID_KEYWORD (progress_gauge, Q_value, check_valid_int);
1490 static void image_instantiator_tree_view (void)
1492 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1493 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1494 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1495 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1496 IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
1497 IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
1498 IIFORMAT_HAS_SHARED_METHOD (tree_view, update, tab_control);
1499 IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1500 VALID_WIDGET_KEYWORDS (tree_view);
1501 VALID_GUI_KEYWORDS (tree_view);
1502 IIFORMAT_VALID_KEYWORD (tree_view, Q_items, check_valid_item_list);
1505 static void image_instantiator_tab_control (void)
1507 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1508 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1509 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1510 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1511 IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
1512 IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
1513 IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1514 IIFORMAT_HAS_METHOD (tab_control, update);
1515 VALID_WIDGET_KEYWORDS (tab_control);
1516 VALID_GUI_KEYWORDS (tab_control);
1517 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation,
1518 check_valid_tab_orientation);
1519 IIFORMAT_VALID_KEYWORD (tab_control, Q_items, check_valid_item_list);
1522 static void image_instantiator_labels (void)
1524 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1525 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1526 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1527 IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget);
1528 IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow);
1529 VALID_WIDGET_KEYWORDS (label);
1530 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1533 #define VALID_LAYOUT_KEYWORDS(layout) \
1534 VALID_WIDGET_KEYWORDS (layout); \
1535 IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \
1536 IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \
1537 IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \
1538 IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \
1539 IIFORMAT_VALID_KEYWORD (layout, Q_items, \
1540 check_valid_instantiator_list)
1542 static void image_instantiator_layout (void)
1544 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1545 IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget);
1546 IIFORMAT_HAS_METHOD (layout, instantiate);
1547 IIFORMAT_HAS_METHOD (layout, post_instantiate);
1548 IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow);
1549 IIFORMAT_HAS_METHOD (layout, normalize);
1550 IIFORMAT_HAS_METHOD (layout, query_geometry);
1551 IIFORMAT_HAS_METHOD (layout, layout);
1552 IIFORMAT_HAS_METHOD (layout, update);
1553 IIFORMAT_HAS_METHOD (layout, property);
1555 VALID_GUI_KEYWORDS (layout);
1556 VALID_LAYOUT_KEYWORDS (layout);
1559 static void image_instantiator_native_layout (void)
1561 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout");
1562 IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget);
1563 IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout);
1564 IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout);
1565 IIFORMAT_HAS_METHOD (native_layout, layout);
1566 IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow);
1567 IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout);
1568 IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout);
1569 IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout);
1570 IIFORMAT_HAS_SHARED_METHOD (native_layout, property, layout);
1572 VALID_GUI_KEYWORDS (native_layout);
1573 VALID_LAYOUT_KEYWORDS (native_layout);
1577 image_instantiator_format_create_glyphs_widget (void)
1579 image_instantiator_widget();
1580 image_instantiator_buttons();
1581 image_instantiator_edit_fields();
1582 image_instantiator_combo_box();
1583 image_instantiator_scrollbar();
1584 image_instantiator_progress_guage();
1585 image_instantiator_tree_view();
1586 image_instantiator_tab_control();
1587 image_instantiator_labels();
1588 image_instantiator_layout();
1589 image_instantiator_native_layout();
1593 reinit_vars_of_glyphs_widget (void)
1595 #ifdef DEBUG_WIDGETS
1596 debug_widget_instances = 0;
1601 vars_of_glyphs_widget (void)
1603 reinit_vars_of_glyphs_widget ();