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);
43 DEFINE_IMAGE_INSTANTIATOR_FORMAT (edit);
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);
55 Lisp_Object Qprogress;
57 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
58 Lisp_Object Q_image, Q_text, Q_percent;
60 #define WIDGET_BORDER_HEIGHT 2
61 #define WIDGET_BORDER_WIDTH 4
64 - more complex controls.
65 - tooltips for controls.
68 /* In windows normal windows work in pixels, dialog boxes work in
69 dialog box units. Why? sigh. We could reuse the metrics for dialogs
70 if this were not the case. As it is we have to position things
71 pixel wise. I'm not even sure that X has this problem at least for
74 widget_face_font_info (Lisp_Object domain, Lisp_Object face,
75 int *height, int *width)
77 Lisp_Object font_instance = FACE_FONT (face, domain, Vcharset_ascii);
80 *height = XFONT_INSTANCE (font_instance)->height;
82 *width = XFONT_INSTANCE (font_instance)->width;
88 widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face,
90 int* height, int* width)
93 widget_face_font_info (domain, face, &ch, &cw);
95 *height = th * (ch + 2 * WIDGET_BORDER_HEIGHT);
97 *width = tw * cw + 2 * WIDGET_BORDER_WIDTH;
101 widget_possible_dest_types (void)
103 return IMAGE_WIDGET_MASK;
107 check_valid_glyph_or_image (Lisp_Object data)
109 Lisp_Object glyph = data;
111 glyph = XSYMBOL (data)->value;
113 if (IMAGE_INSTANCEP (glyph))
114 CHECK_IMAGE_INSTANCE (glyph);
115 else if (!CONSP (glyph))
116 CHECK_BUFFER_GLYPH (glyph);
120 check_valid_anything (Lisp_Object data)
125 check_valid_callback (Lisp_Object data)
128 && !COMPILED_FUNCTIONP (data)
131 signal_simple_error (":callback must be a function or expression", data);
136 check_valid_symbol (Lisp_Object data)
142 check_valid_string_or_vector (Lisp_Object data)
144 if (!STRINGP (data) && !VECTORP (data))
145 signal_simple_error (":descriptor must be a string or a vector", data);
149 check_valid_item_list (Lisp_Object data)
153 Fcheck_valid_plist (data);
155 items = Fplist_get (data, Q_items, Qnil);
158 EXTERNAL_LIST_LOOP (rest, items)
160 CHECK_STRING (XCAR (rest));
164 /* wire widget property invocations to specific widgets ... The
165 problem we are solving here is that when instantiators get converted
166 to instances they lose some type information (they just become
167 subwindows or widgets for example). For widgets we need to preserve
168 this type information so that we can do widget specific operations on
169 the instances. This is encoded in the widget type
170 field. widget_property gets invoked by decoding the primary type
171 (Qwidget), widget property then invokes based on the secondary type
172 (Qedit for example). It is debatable that we should wire things in this
173 generalised way rather than treating widgets specially in
174 image_instance_property. */
176 widget_property (Lisp_Object image_instance, Lisp_Object prop)
178 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
179 struct image_instantiator_methods* meths;
181 /* first see if its a general property ... */
182 if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
183 return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
185 /* .. then try device specific methods ... */
186 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
187 IMAGE_INSTANCE_WIDGET_TYPE (ii),
189 if (meths && HAS_IIFORMAT_METH_P (meths, property))
190 return IIFORMAT_METH (meths, property, (image_instance, prop));
191 /* ... then format specific methods ... */
192 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
194 if (meths && HAS_IIFORMAT_METH_P (meths, property))
195 return IIFORMAT_METH (meths, property, (image_instance, prop));
201 widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
203 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
204 struct image_instantiator_methods* meths;
207 /* try device specific methods first ... */
208 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
209 IMAGE_INSTANCE_WIDGET_TYPE (ii),
211 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
214 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
218 /* ... then format specific methods ... */
219 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
221 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
224 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
228 /* we didn't do any device specific properties, so shove the property in our plist */
229 IMAGE_INSTANCE_WIDGET_PROPS (ii)
230 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
235 widget_validate (Lisp_Object instantiator)
237 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
240 signal_simple_error ("Must supply :descriptor", instantiator);
243 gui_parse_item_keywords (desc, &gui);
245 if (!NILP (find_keyword_in_vector (instantiator, Q_width))
246 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
247 signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
249 if (!NILP (find_keyword_in_vector (instantiator, Q_height))
250 && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
251 signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
255 combo_validate (Lisp_Object instantiator)
257 widget_validate (instantiator);
258 if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
259 signal_simple_error ("Must supply item list", instantiator);
262 /* we need to convert things like glyphs to images, eval expressions
265 widget_normalize (Lisp_Object inst, Lisp_Object console_type)
267 /* This function can call lisp */
268 Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
270 /* we need to eval glyph if its an expression, we do this for the
271 same reasons we normalize file to data. */
277 glyph = XSYMBOL (glyph)->value;
281 glyph = Feval (glyph);
282 /* substitute the new glyph */
283 for (i = 0; i < XVECTOR_LENGTH (inst); i++)
285 if (EQ (Q_image, XVECTOR_DATA (inst)[i]))
287 XVECTOR_DATA (inst)[i+1] = glyph;
297 initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object type)
299 /* initialize_subwindow_image_instance (ii);*/
300 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
301 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
302 IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face;
303 gui_item_init (&IMAGE_INSTANCE_WIDGET_ITEM (ii));
306 /* Instantiate a button widget. Unfortunately instantiated widgets are
307 particular to a frame since they need to have a parent. It's not
308 like images where you just select the image into the context you
309 want to display it in and BitBlt it. So images instances can have a
310 many-to-one relationship with things you see, whereas widgets can
311 only be one-to-one (i.e. per frame) */
313 widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
314 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
315 int dest_mask, Lisp_Object domain, int default_textheight,
316 int default_pixheight)
318 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
319 struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
320 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
321 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
322 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
323 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
324 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
325 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
326 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
327 int pw=0, ph=0, tw=0, th=0;
329 /* this just does pixel type sizing */
330 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
333 if (!(dest_mask & IMAGE_WIDGET_MASK))
334 incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
336 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
338 /* retrieve the fg and bg colors */
340 IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face);
342 /* data items for some widgets */
343 IMAGE_INSTANCE_WIDGET_PROPS (ii) =
344 find_keyword_in_vector (instantiator, Q_properties);
346 /* retrieve the gui item information. This is easy if we have been
347 provided with a vector, more difficult if we have just been given
349 if (STRINGP (desc) || NILP (desc))
351 /* big cheat - we rely on the fact that a gui item looks like an instantiator */
352 gui_parse_item_keywords_no_errors (instantiator, pgui);
353 IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
356 gui_parse_item_keywords_no_errors (desc, pgui);
358 /* normalize size information */
363 if (!NILP (pixwidth))
364 pw = XINT (pixwidth);
365 if (!NILP (pixheight))
366 ph = XINT (pixheight);
368 /* for a widget with an image pick up the dimensions from that */
372 pw = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain)
373 + 2 * WIDGET_BORDER_WIDTH;
375 ph = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain)
376 + 2 * WIDGET_BORDER_HEIGHT;
379 /* if we still don' t have sizes, guess from text size */
380 if (!tw && !pw && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
381 tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii));
384 if (default_textheight)
385 th = default_textheight;
386 else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
389 ph = default_pixheight;
392 if (tw !=0 || th !=0)
393 widget_text_to_pixel_conversion (domain,
394 IMAGE_INSTANCE_WIDGET_FACE (ii),
395 th, tw, th ? &ph : 0, tw ? &pw : 0);
397 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw;
398 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph;
402 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
403 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
404 int dest_mask, Lisp_Object domain)
406 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
407 pointer_bg, dest_mask, domain, 1, 0);
411 combo_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
412 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
413 int dest_mask, Lisp_Object domain)
415 Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
418 GET_LIST_LENGTH (data, len);
419 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
420 pointer_bg, dest_mask, domain, len + 1, 0);
423 /* Instantiate a static control */
425 static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
426 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
427 int dest_mask, Lisp_Object domain)
429 widget_instantiate_1 (image_instance, instantiator, pointer_fg,
430 pointer_bg, dest_mask, domain, 0, 4);
434 /************************************************************************/
436 /************************************************************************/
439 syms_of_glyphs_widget (void)
441 defkeyword (&Q_descriptor, ":descriptor");
442 defkeyword (&Q_height, ":height");
443 defkeyword (&Q_width, ":width");
444 defkeyword (&Q_properties, ":properties");
445 defkeyword (&Q_items, ":items");
446 defkeyword (&Q_image, ":image");
447 defkeyword (&Q_percent, ":percent");
448 defkeyword (&Q_text, "text");
452 image_instantiator_format_create_glyphs_widget (void)
454 #define VALID_GUI_KEYWORDS(type) \
455 IIFORMAT_VALID_KEYWORD (type, Q_active, check_valid_anything); \
456 IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything); \
457 IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string); \
458 IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol); \
459 IIFORMAT_VALID_KEYWORD (type, Q_selected, check_valid_anything); \
460 IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything); \
461 IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol); \
462 IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything); \
463 IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string); \
464 IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \
465 IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \
466 IIFORMAT_VALID_KEYWORD (type, Q_callback, check_valid_callback); \
467 IIFORMAT_VALID_KEYWORD (type, Q_descriptor, check_valid_string_or_vector)
469 #define VALID_WIDGET_KEYWORDS(type) \
470 IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \
471 IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \
472 IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int); \
473 IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int); \
474 IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face)
476 /* we only do this for properties */
477 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
478 IIFORMAT_HAS_METHOD (widget, property);
479 IIFORMAT_HAS_METHOD (widget, set_property);
481 /* widget image-instantiator types - buttons */
482 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
483 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
484 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
485 IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
486 IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
487 IIFORMAT_VALID_KEYWORD (button, Q_image, check_valid_glyph_or_image);
488 VALID_WIDGET_KEYWORDS (button);
489 VALID_GUI_KEYWORDS (button);
492 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit, "edit");
493 IIFORMAT_HAS_SHARED_METHOD (edit, validate, widget);
494 IIFORMAT_HAS_SHARED_METHOD (edit, possible_dest_types, widget);
495 IIFORMAT_HAS_SHARED_METHOD (edit, instantiate, widget);
496 VALID_WIDGET_KEYWORDS (edit);
497 VALID_GUI_KEYWORDS (edit);
500 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo, "combo");
501 IIFORMAT_HAS_METHOD (combo, validate);
502 IIFORMAT_HAS_SHARED_METHOD (combo, possible_dest_types, widget);
503 IIFORMAT_HAS_METHOD (combo, instantiate);
504 VALID_GUI_KEYWORDS (combo);
506 IIFORMAT_VALID_KEYWORD (combo, Q_width, check_valid_int);
507 IIFORMAT_VALID_KEYWORD (combo, Q_height, check_valid_int);
508 IIFORMAT_VALID_KEYWORD (combo, Q_pixel_width, check_valid_int);
509 IIFORMAT_VALID_KEYWORD (combo, Q_face, check_valid_face);
510 IIFORMAT_VALID_KEYWORD (combo, Q_properties, check_valid_item_list);
513 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
514 IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
515 IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
516 IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
517 VALID_GUI_KEYWORDS (scrollbar);
519 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
520 IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
521 IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
524 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress, "progress");
525 IIFORMAT_HAS_SHARED_METHOD (progress, validate, widget);
526 IIFORMAT_HAS_SHARED_METHOD (progress, possible_dest_types, widget);
527 IIFORMAT_HAS_SHARED_METHOD (progress, instantiate, widget);
528 VALID_WIDGET_KEYWORDS (progress);
529 VALID_GUI_KEYWORDS (progress);
532 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
533 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
534 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, static);
535 VALID_WIDGET_KEYWORDS (label);
536 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
540 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (group, "group");
541 IIFORMAT_HAS_SHARED_METHOD (group, possible_dest_types, widget);
542 IIFORMAT_HAS_METHOD (group, instantiate);
544 IIFORMAT_VALID_KEYWORD (group, Q_width, check_valid_int);
545 IIFORMAT_VALID_KEYWORD (group, Q_height, check_valid_int);
546 IIFORMAT_VALID_KEYWORD (group, Q_pixel_width, check_valid_int);
547 IIFORMAT_VALID_KEYWORD (group, Q_pixel_height, check_valid_int);
548 IIFORMAT_VALID_KEYWORD (group, Q_face, check_valid_face);
549 IIFORMAT_VALID_KEYWORD (group, Q_background, check_valid_string);
550 IIFORMAT_VALID_KEYWORD (group, Q_descriptor, check_valid_string);
555 vars_of_glyphs_widget (void)