1 /* Widget-specific glyph objects.
2 Copyright (C) 1998 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);
49 DEFINE_IMAGE_INSTANTIATOR_FORMAT (group);
52 DEFINE_IMAGE_INSTANTIATOR_FORMAT (label);
54 DEFINE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge);
55 Lisp_Object Qprogress_gauge;
56 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tree_view);
57 Lisp_Object Qtree_view;
58 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control);
59 Lisp_Object Qtab_control;
61 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
62 Lisp_Object Q_image, Q_text, Q_percent;
64 #define WIDGET_BORDER_HEIGHT 2
65 #define WIDGET_BORDER_WIDTH 4
68 - more complex controls.
69 - tooltips for controls.
72 /* In windows normal windows work in pixels, dialog boxes work in
73 dialog box units. Why? sigh. We could reuse the metrics for dialogs
74 if this were not the case. As it is we have to position things
75 pixel wise. I'm not even sure that X has this problem at least for
78 widget_face_font_info (Lisp_Object domain, Lisp_Object face,
79 int *height, int *width)
81 Lisp_Object font_instance = FACE_FONT (face, domain, Vcharset_ascii);
84 *height = XFONT_INSTANCE (font_instance)->height;
86 *width = XFONT_INSTANCE (font_instance)->width;
92 widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face,
94 int* height, int* width)
97 widget_face_font_info (domain, face, &ch, &cw);
99 *height = th * (ch + 2 * WIDGET_BORDER_HEIGHT);
101 *width = tw * cw + 2 * WIDGET_BORDER_WIDTH;
105 widget_possible_dest_types (void)
107 return IMAGE_WIDGET_MASK;
111 check_valid_glyph_or_image (Lisp_Object data)
113 Lisp_Object glyph = data;
115 glyph = XSYMBOL (data)->value;
117 if (IMAGE_INSTANCEP (glyph))
118 CHECK_IMAGE_INSTANCE (glyph);
119 else if (!CONSP (glyph))
120 CHECK_BUFFER_GLYPH (glyph);
124 check_valid_anything (Lisp_Object data)
129 check_valid_callback (Lisp_Object data)
132 && !COMPILED_FUNCTIONP (data)
135 signal_simple_error (":callback must be a function or expression", data);
140 check_valid_symbol (Lisp_Object data)
146 check_valid_string_or_vector (Lisp_Object data)
148 if (!STRINGP (data) && !VECTORP (data))
149 signal_simple_error (":descriptor must be a string or a vector", data);
153 check_valid_item_list_1 (Lisp_Object items)
158 EXTERNAL_LIST_LOOP (rest, items)
160 if (STRINGP (XCAR (rest)))
161 CHECK_STRING (XCAR (rest));
162 else if (VECTORP (XCAR (rest)))
163 gui_parse_item_keywords (XCAR (rest));
164 else if (LISTP (XCAR (rest)))
165 check_valid_item_list_1 (XCAR (rest));
167 signal_simple_error ("Items must be vectors, lists or strings", items);
172 check_valid_item_list (Lisp_Object data)
176 Fcheck_valid_plist (data);
177 items = Fplist_get (data, Q_items, Qnil);
179 check_valid_item_list_1 (items);
182 /* wire widget property invocations to specific widgets ... The
183 problem we are solving here is that when instantiators get converted
184 to instances they lose some type information (they just become
185 subwindows or widgets for example). For widgets we need to preserve
186 this type information so that we can do widget specific operations on
187 the instances. This is encoded in the widget type
188 field. widget_property gets invoked by decoding the primary type
189 (Qwidget), widget property then invokes based on the secondary type
190 (Qedit_field for example). It is debatable that we should wire things in this
191 generalised way rather than treating widgets specially in
192 image_instance_property. */
194 widget_property (Lisp_Object image_instance, Lisp_Object prop)
196 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
197 struct image_instantiator_methods* meths;
199 /* first see if its a general property ... */
200 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
201 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
203 /* .. then try device specific methods ... */
204 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
205 IMAGE_INSTANCE_WIDGET_TYPE (ii),
207 if (meths && HAS_IIFORMAT_METH_P (meths, property))
208 return IIFORMAT_METH (meths, property, (image_instance, prop));
209 /* ... then format specific methods ... */
210 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
212 if (meths && HAS_IIFORMAT_METH_P (meths, property))
213 return IIFORMAT_METH (meths, property, (image_instance, prop));
219 widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
221 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
222 struct image_instantiator_methods* meths;
225 /* try device specific methods first ... */
226 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
227 IMAGE_INSTANCE_WIDGET_TYPE (ii),
229 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
232 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
236 /* ... then format specific methods ... */
237 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
239 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
242 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
246 /* we didn't do any device specific properties, so shove the property in our plist */
247 IMAGE_INSTANCE_WIDGET_PROPS (ii)
248 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
253 widget_validate (Lisp_Object instantiator)
255 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
258 signal_simple_error ("Must supply :descriptor", instantiator);
261 gui_parse_item_keywords (desc);
263 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
264 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
265 signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
267 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
268 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
269 signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
273 combo_box_validate (Lisp_Object instantiator)
275 widget_validate (instantiator);
276 if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
277 signal_simple_error ("Must supply item list", instantiator);
280 /* we need to convert things like glyphs to images, eval expressions
283 widget_normalize (Lisp_Object inst, Lisp_Object console_type)
285 /* This function can call lisp */
286 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
288 /* we need to eval glyph if its an expression, we do this for the
289 same reasons we normalize file to data. */
295 glyph = XSYMBOL (glyph)->value;
299 glyph = Feval (glyph);
300 /* substitute the new glyph */
301 for (i = 0; i < XVECTOR_LENGTH (inst); i++)
303 if (EQ (Q_image, XVECTOR_DATA (inst)[i]))
305 XVECTOR_DATA (inst)[i+1] = glyph;
315 initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object type)
317 /* initialize_subwindow_image_instance (ii);*/
318 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
319 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
320 IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face;
321 IMAGE_INSTANCE_WIDGET_ITEM (ii) = allocate_gui_item ();
324 /* Instantiate a button widget. Unfortunately instantiated widgets are
325 particular to a frame since they need to have a parent. It's not
326 like images where you just select the image into the context you
327 want to display it in and BitBlt it. So image instances can have a
328 many-to-one relationship with things you see, whereas widgets can
329 only be one-to-one (i.e. per frame) */
331 widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
332 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
333 int dest_mask, Lisp_Object domain, int default_textheight,
334 int default_pixheight, int default_textwidth)
336 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
337 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
338 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
339 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
340 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
341 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
342 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
343 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
344 int pw=0, ph=0, tw=0, th=0;
346 /* this just does pixel type sizing */
347 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
350 if (!(dest_mask & IMAGE_WIDGET_MASK))
351 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
353 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
355 /* retrieve the fg and bg colors */
357 IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face);
359 /* data items for some widgets */
360 IMAGE_INSTANCE_WIDGET_PROPS (ii) =
361 find_keyword_in_vector (instantiator, Q_properties);
363 /* retrieve the gui item information. This is easy if we have been
364 provided with a vector, more difficult if we have just been given
366 if (STRINGP (desc) || NILP (desc))
368 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
369 IMAGE_INSTANCE_WIDGET_ITEM (ii) =
370 gui_parse_item_keywords_no_errors (instantiator);
371 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
374 IMAGE_INSTANCE_WIDGET_ITEM (ii) =
375 gui_parse_item_keywords_no_errors (desc);
377 /* normalize size information */
382 if (!NILP (pixwidth))
383 pw = XINT (pixwidth);
384 if (!NILP (pixheight))
385 ph = XINT (pixheight);
387 /* for a widget with an image pick up the dimensions from that */
391 pw = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain)
392 + 2 * WIDGET_BORDER_WIDTH;
394 ph = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain)
395 + 2 * WIDGET_BORDER_HEIGHT;
398 /* if we still don' t have sizes, guess from text size */
401 if (default_textwidth)
402 tw = default_textwidth;
403 else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
404 tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii));
409 if (default_textheight)
410 th = default_textheight;
411 else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
414 ph = default_pixheight;
417 if (tw !=0 || th !=0)
418 widget_text_to_pixel_conversion (domain,
419 IMAGE_INSTANCE_WIDGET_FACE (ii),
420 th, tw, th ? &ph : 0, tw ? &pw : 0);
422 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw;
423 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph;
427 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
428 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
429 int dest_mask, Lisp_Object domain)
431 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
432 pointer_bg, dest_mask, domain, 1, 0, 0);
435 /* combo-box generic instantiation - get he heigh right */
437 combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
438 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
439 int dest_mask, Lisp_Object domain)
441 Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
444 GET_LIST_LENGTH (data, len);
445 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
446 pointer_bg, dest_mask, domain, len + 1, 0, 0);
450 tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
451 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
452 int dest_mask, Lisp_Object domain)
454 Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
459 LIST_LOOP (rest, data)
461 len += 3; /* some bias */
462 if (STRINGP (XCAR (rest)))
463 len += XSTRING_LENGTH (XCAR (rest));
464 else if (VECTORP (XCAR (rest)))
466 Lisp_Object gui = gui_parse_item_keywords (XCAR (rest));
467 len += XSTRING_LENGTH (XGUI_ITEM (gui)->name);
471 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
472 pointer_bg, dest_mask, domain, 0, 0, len);
475 /* Instantiate a static control */
477 static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
478 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
479 int dest_mask, Lisp_Object domain)
481 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
482 pointer_bg, dest_mask, domain, 0, 4, 0);
486 /************************************************************************/
488 /************************************************************************/
491 syms_of_glyphs_widget (void)
493 defkeyword (&Q_descriptor, ":descriptor");
494 defkeyword (&Q_height, ":height");
495 defkeyword (&Q_width, ":width");
496 defkeyword (&Q_properties, ":properties");
497 defkeyword (&Q_items, ":items");
498 defkeyword (&Q_image, ":image");
499 defkeyword (&Q_percent, ":percent");
500 defkeyword (&Q_text, ":text");
504 image_instantiator_format_create_glyphs_widget (void)
506 #define VALID_GUI_KEYWORDS(type) \
507 IIFORMAT_VALID_KEYWORD (type, Q_active, check_valid_anything); \
508 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
509 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
510 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
511 IIFORMAT_VALID_KEYWORD (type, Q_selected, check_valid_anything); \
512 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
513 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
514 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
515 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
516 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
517 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
518 IIFORMAT_VALID_KEYWORD (type, Q_callback, check_valid_callback); \
519 IIFORMAT_VALID_KEYWORD (type, Q_descriptor, check_valid_string_or_vector)
521 #define VALID_WIDGET_KEYWORDS(type) \
522 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
523 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
524 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int); \
525 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int); \
526 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face)
528 /* we only do this for properties */
529 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
530 IIFORMAT_HAS_METHOD (widget, property);
531 IIFORMAT_HAS_METHOD (widget, set_property);
533 /* widget image-instantiator types - buttons */
534 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
535 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
536 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
537 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
538 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
539 IIFORMAT_VALID_KEYWORD (button, Q_image, check_valid_glyph_or_image);
540 VALID_WIDGET_KEYWORDS (button);
541 VALID_GUI_KEYWORDS (button);
544 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
545 IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
546 IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
547 IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
548 VALID_WIDGET_KEYWORDS (edit_field);
549 VALID_GUI_KEYWORDS (edit_field);
552 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
553 IIFORMAT_HAS_METHOD (combo_box, validate);
554 IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
555 IIFORMAT_HAS_METHOD (combo_box, instantiate);
556 VALID_GUI_KEYWORDS (combo_box);
558 IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
559 IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
560 IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int);
561 IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
562 IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list);
565 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
566 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
567 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
568 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
569 VALID_GUI_KEYWORDS (scrollbar);
571 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
572 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
573 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
576 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
577 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
578 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
579 IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, combo_box);
580 VALID_WIDGET_KEYWORDS (progress_gauge);
581 VALID_GUI_KEYWORDS (progress_gauge);
584 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
585 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
586 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
587 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, combo_box);
588 VALID_WIDGET_KEYWORDS (tree_view);
589 VALID_GUI_KEYWORDS (tree_view);
590 IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
593 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
594 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
595 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
596 IIFORMAT_HAS_METHOD (tab_control, instantiate);
597 VALID_WIDGET_KEYWORDS (tab_control);
598 VALID_GUI_KEYWORDS (tab_control);
599 IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
602 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
603 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
604 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, static);
605 VALID_WIDGET_KEYWORDS (label);
606 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
610 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (group, "group");
611 IIFORMAT_HAS_SHARED_METHOD (group, possible_dest_types, widget);
612 IIFORMAT_HAS_METHOD (group, instantiate);
614 IIFORMAT_VALID_KEYWORD (group, Q_width, check_valid_int);
615 IIFORMAT_VALID_KEYWORD (group, Q_height, check_valid_int);
616 IIFORMAT_VALID_KEYWORD (group, Q_pixel_width, check_valid_int);
617 IIFORMAT_VALID_KEYWORD (group, Q_pixel_height, check_valid_int);
618 IIFORMAT_VALID_KEYWORD (group, Q_face, check_valid_face);
619 IIFORMAT_VALID_KEYWORD (group, Q_background, check_valid_string);
620 IIFORMAT_VALID_KEYWORD (group, Q_descriptor, check_valid_string);
625 vars_of_glyphs_widget (void)