comparison src/glyphs-widget.c @ 438:84b14dcb0985 r21-2-27

Import from CVS: tag r21-2-27
author cvs
date Mon, 13 Aug 2007 11:32:25 +0200
parents 9d177e8d4150
children 8de8e3f6228a
comparison
equal deleted inserted replaced
437:e2a4e8b94b82 438:84b14dcb0985
1 /* Widget-specific glyph objects. 1 /* Widget-specific glyph objects.
2 Copyright (C) 1998, 1999 Andy Piper. 2 Copyright (C) 1998, 1999, 2000 Andy Piper.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 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 7 under the terms of the GNU General Public License as published by the
58 58
59 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items; 59 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
60 Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border; 60 Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border;
61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; 61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
62 62
63 #define WIDGET_BORDER_HEIGHT 4
64 #define WIDGET_BORDER_WIDTH 4
65
66 #ifdef DEBUG_WIDGETS 63 #ifdef DEBUG_WIDGETS
67 int debug_widget_instances; 64 int debug_widget_instances;
68 #endif 65 #endif
69 66
70 /* TODO: 67 /* TODO:
71 - more complex controls. 68 - more complex controls.
72 - tooltips for controls. 69 - tooltips for controls, especially buttons.
73 */ 70 */
74 71
75 /* In windows normal windows work in pixels, dialog boxes work in 72 /* 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 73 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 74 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 75 pixel wise. I'm not even sure that X has this problem at least for
79 buttons in groups. */ 76 buttons in groups. */
80 Lisp_Object
81 widget_face_font_info (Lisp_Object domain, Lisp_Object face,
82 int *height, int *width)
83 {
84 Lisp_Object font_instance = FACE_FONT (face, domain, Vcharset_ascii);
85
86 if (height)
87 *height = XFONT_INSTANCE (font_instance)->height;
88 if (width)
89 *width = XFONT_INSTANCE (font_instance)->width;
90
91 return font_instance;
92 }
93
94 void
95 widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face,
96 int th, int tw,
97 int* height, int* width)
98 {
99 int ch=0, cw=0;
100 widget_face_font_info (domain, face, &ch, &cw);
101 if (height)
102 *height = th * ch + 2 * WIDGET_BORDER_HEIGHT;
103 if (width)
104 *width = tw * cw + 2 * WIDGET_BORDER_WIDTH;
105 }
106
107 static int 77 static int
108 widget_possible_dest_types (void) 78 widget_possible_dest_types (void)
109 { 79 {
110 return IMAGE_WIDGET_MASK; 80 return IMAGE_WIDGET_MASK;
111 } 81 }
128 { 98 {
129 if (!EQ (data, Qhorizontal) 99 if (!EQ (data, Qhorizontal)
130 && 100 &&
131 !EQ (data, Qvertical)) 101 !EQ (data, Qvertical))
132 signal_simple_error ("unknown orientation for layout", data); 102 signal_simple_error ("unknown orientation for layout", data);
103 }
104
105 static void
106 check_valid_tab_orientation (Lisp_Object data)
107 {
108 if (!EQ (data, Qtop)
109 &&
110 !EQ (data, Qbottom)
111 &&
112 !EQ (data, Qleft)
113 &&
114 !EQ (data, Qright))
115 signal_simple_error ("unknown orientation for tab control", data);
133 } 116 }
134 117
135 static void 118 static void
136 check_valid_justification (Lisp_Object data) 119 check_valid_justification (Lisp_Object data)
137 { 120 {
257 break; 240 break;
258 } 241 }
259 } 242 }
260 } 243 }
261 244
262 /* wire widget property invocations to specific widgets ... The 245 /* Wire widget property invocations to specific widgets. The problem
263 problem we are solving here is that when instantiators get converted 246 we are solving here is that when instantiators get converted to
264 to instances they lose some type information (they just become 247 instances they lose some type information (they just become
265 subwindows or widgets for example). For widgets we need to preserve 248 subwindows or widgets for example). For widgets we need to preserve
266 this type information so that we can do widget specific operations on 249 this type information so that we can do widget specific operations
267 the instances. This is encoded in the widget type 250 on the instances. This is encoded in the widget type
268 field. widget_property gets invoked by decoding the primary type 251 field. widget_property gets invoked by decoding the primary type
269 (Qwidget), widget property then invokes based on the secondary type 252 (Qwidget), <widget>_property then invokes based on the secondary
270 (Qedit_field for example). It is debatable that we should wire things in this 253 type (Qedit_field for example). It is debatable whether we should
271 generalised way rather than treating widgets specially in 254 wire things in this generalised way rather than treating widgets
272 image_instance_property. */ 255 specially in image_instance_property. */
273 static Lisp_Object 256 static Lisp_Object
274 widget_property (Lisp_Object image_instance, Lisp_Object prop) 257 widget_property (Lisp_Object image_instance, Lisp_Object prop)
275 { 258 {
276 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 259 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
277 struct image_instantiator_methods* meths; 260 struct image_instantiator_methods* meths;
300 { 283 {
301 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); 284 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
302 struct image_instantiator_methods* meths; 285 struct image_instantiator_methods* meths;
303 Lisp_Object ret; 286 Lisp_Object ret;
304 287
305 /* try device specific methods first ... */ 288 /* PIck up any generic properties that we might need to keep hold
289 of. */
290 if (EQ (prop, Q_text))
291 {
292 IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
293 }
294
295 /* Now try device specific methods first ... */
306 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 296 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
307 IMAGE_INSTANCE_WIDGET_TYPE (ii), 297 IMAGE_INSTANCE_WIDGET_TYPE (ii),
308 ERROR_ME_NOT); 298 ERROR_ME_NOT);
309 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) 299 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
310 && 300 &&
327 IMAGE_INSTANCE_WIDGET_PROPS (ii) 317 IMAGE_INSTANCE_WIDGET_PROPS (ii)
328 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val); 318 = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
329 return val; 319 return val;
330 } 320 }
331 321
322 /* Query for a widgets desired geometry. If no type specific method is
323 provided then use the widget text to calculate sizes. */
324 static void
325 widget_query_geometry (Lisp_Object image_instance,
326 unsigned int* width, unsigned int* height,
327 enum image_instance_geometry disp, Lisp_Object domain)
328 {
329 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
330 struct image_instantiator_methods* meths;
331
332 /* First just set up what we already have. */
333 if (width) *width = IMAGE_INSTANCE_WIDTH (ii);
334 if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
335
336 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
337 ||
338 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
339 {
340 /* .. then try device specific methods ... */
341 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
342 IMAGE_INSTANCE_WIDGET_TYPE (ii),
343 ERROR_ME_NOT);
344 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
345 IIFORMAT_METH (meths, query_geometry, (image_instance,
346 width, height, disp,
347 domain));
348 else
349 {
350 /* ... then format specific methods ... */
351 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
352 ERROR_ME_NOT);
353 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
354 IIFORMAT_METH (meths, query_geometry, (image_instance,
355 width, height, disp,
356 domain));
357 else
358 {
359 unsigned int w, h;
360
361 /* Then if we are allowed to resize the widget, make the
362 size the same as the text dimensions. */
363 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
364 IMAGE_INSTANCE_WIDGET_FACE (ii),
365 &w, &h, 0, domain);
366 /* Adjust the size for borders. */
367 if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
368 *width = w + 2 * WIDGET_BORDER_WIDTH;
369 if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
370 *height = h + 2 * WIDGET_BORDER_HEIGHT;
371 }
372 }
373 }
374 }
375
376 static void
377 widget_layout (Lisp_Object image_instance,
378 unsigned int width, unsigned int height, Lisp_Object domain)
379 {
380 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
381 struct image_instantiator_methods* meths;
382
383 /* .. then try device specific methods ... */
384 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
385 IMAGE_INSTANCE_WIDGET_TYPE (ii),
386 ERROR_ME_NOT);
387 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
388 IIFORMAT_METH (meths, layout, (image_instance,
389 width, height, domain));
390 else
391 {
392 /* ... then format specific methods ... */
393 meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
394 ERROR_ME_NOT);
395 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
396 IIFORMAT_METH (meths, layout, (image_instance,
397 width, height, domain));
398 }
399 }
400
332 static void 401 static void
333 widget_validate (Lisp_Object instantiator) 402 widget_validate (Lisp_Object instantiator)
334 { 403 {
335 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); 404 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
336 405
379 initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object type) 448 initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object type)
380 { 449 {
381 /* initialize_subwindow_image_instance (ii);*/ 450 /* initialize_subwindow_image_instance (ii);*/
382 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type; 451 IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
383 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; 452 IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
384 IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face; 453 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
385 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); 454 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
455 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
456 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
457 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0;
458 IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
386 } 459 }
387 460
388 /* Instantiate a button widget. Unfortunately instantiated widgets are 461 /* Instantiate a button widget. Unfortunately instantiated widgets are
389 particular to a frame since they need to have a parent. It's not 462 particular to a frame since they need to have a parent. It's not
390 like images where you just select the image into the context you 463 like images where you just select the image into the context you
391 want to display it in and BitBlt it. So image instances can have a 464 want to display it in and BitBlt it. So image instances can have a
392 many-to-one relationship with things you see, whereas widgets can 465 many-to-one relationship with things you see, whereas widgets can
393 only be one-to-one (i.e. per frame) */ 466 only be one-to-one (i.e. per frame) */
394 void 467 void
395 widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, 468 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
396 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 469 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
397 int dest_mask, Lisp_Object domain, int default_textheight, 470 int dest_mask, Lisp_Object domain)
398 int default_pixheight, int default_textwidth)
399 { 471 {
400 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 472 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
401 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face); 473 Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
402 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height); 474 Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
403 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width); 475 Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
404 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width); 476 Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
405 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height); 477 Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
406 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); 478 Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
407 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); 479 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
408 Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties); 480 Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
481 Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
409 int pw=0, ph=0, tw=0, th=0; 482 int pw=0, ph=0, tw=0, th=0;
410 483
411 /* this just does pixel type sizing */ 484 /* this just does pixel type sizing */
412 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, 485 subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
413 dest_mask, domain); 486 dest_mask, domain);
417 490
418 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]); 491 initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
419 492
420 /* retrieve the fg and bg colors */ 493 /* retrieve the fg and bg colors */
421 if (!NILP (face)) 494 if (!NILP (face))
422 IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face); 495 SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
423 496
424 /* data items for some widgets */ 497 /* data items for some widgets */
425 IMAGE_INSTANCE_WIDGET_PROPS (ii) = props; 498 IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
499
500 /* Pick up the orientation before we do our first layout. */
501 if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
502 IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1;
426 503
427 /* retrieve the gui item information. This is easy if we have been 504 /* retrieve the gui item information. This is easy if we have been
428 provided with a vector, more difficult if we have just been given 505 provided with a vector, more difficult if we have just been given
429 keywords */ 506 keywords */
430 if (STRINGP (desc) || NILP (desc)) 507 if (STRINGP (desc) || NILP (desc))
446 IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 523 IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
447 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), 524 Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
448 parse_gui_item_tree_children (items)); 525 parse_gui_item_tree_children (items));
449 } 526 }
450 527
451 /* normalize size information */ 528 /* Normalize size information. We now only assign sizes if the user
452 if (!NILP (width)) 529 gives us some explicitly, or there are some constraints that we
453 tw = XINT (width); 530 can't change later on. Otherwise we postpone sizing until query
454 if (!NILP (height)) 531 geometry gets called. */
455 th = XINT (height); 532 if (!NILP (pixwidth)) /* pixwidth takes precendent */
456 if (!NILP (pixwidth)) 533 {
457 pw = XINT (pixwidth); 534 pw = XINT (pixwidth);
535 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
536 }
537 else if (!NILP (width))
538 {
539 tw = XINT (width);
540 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
541 }
542
458 if (!NILP (pixheight)) 543 if (!NILP (pixheight))
459 ph = XINT (pixheight); 544 {
545 ph = XINT (pixheight);
546 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
547 }
548 else if (!NILP (height) && XINT (height) > 1)
549 {
550 th = XINT (height);
551 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
552 }
553
554 /* Taking the default face information when the user has specified
555 size in characters is probably as good as any since the widget
556 face is more likely to be proportional and thus give inadequate
557 results. Using character sizes can only ever be approximate
558 anyway. */
559 if (tw || th)
560 {
561 int charwidth, charheight;
562 default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
563 if (tw)
564 pw = charwidth * tw;
565 if (th)
566 ph = charheight * th;
567 }
460 568
461 /* for a widget with an image pick up the dimensions from that */ 569 /* for a widget with an image pick up the dimensions from that */
462 if (!NILP (glyph)) 570 if (!NILP (glyph))
463 { 571 {
464 if (!pw && !tw) 572 if (!pw)
465 pw = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain) 573 pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH;
466 + 2 * WIDGET_BORDER_WIDTH; 574 if (!ph)
467 if (!ph && !th) 575 ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT;
468 ph = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain) 576 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
469 + 2 * WIDGET_BORDER_HEIGHT; 577 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
470 } 578 }
471 579
472 /* if we still don' t have sizes, guess from text size */ 580 /* have to set the type this late in case there is no device
473 if (!tw && !pw) 581 instantiation for a widget */
474 { 582 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
475 if (default_textwidth) 583
476 tw = default_textwidth; 584 /* When we create the widgets the window system expects a valid
477 else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) 585 size, so If we still don' t have sizes, call layout to pick them
478 tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii)); 586 up. If query_geometry or layout relies on the widget being in
479 } 587 existence then we are in catch 22. */
480 588 image_instance_layout (image_instance,
481 if (!th && !ph) 589 pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
482 { 590 ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
483 if (default_textheight) 591 domain);
484 th = default_textheight; 592 /* Layout has already been done so we don't need to re-layout. */
485 else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) 593 IMAGE_INSTANCE_DIRTYP (ii) = 0;
486 th = 1; 594
487 else
488 ph = default_pixheight;
489 }
490
491 if (tw !=0 || th !=0)
492 widget_text_to_pixel_conversion (domain,
493 IMAGE_INSTANCE_WIDGET_FACE (ii),
494 th, tw, th ? &ph : 0, tw ? &pw : 0);
495
496 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw;
497 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph;
498 #ifdef DEBUG_WIDGETS 595 #ifdef DEBUG_WIDGETS
499 debug_widget_instances++; 596 debug_widget_instances++;
500 stderr_out ("instantiated "); 597 stderr_out ("instantiated ");
501 debug_print (instantiator); 598 debug_print (instantiator);
502 stderr_out ("%d widgets instantiated\n", debug_widget_instances); 599 stderr_out ("%d widgets instantiated\n", debug_widget_instances);
503 #endif 600 #endif
504 } 601 }
505 602
506 static void 603 /* tree-view geometry - get the height right */
507 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 604 static void
508 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 605 tree_view_query_geometry (Lisp_Object image_instance,
509 int dest_mask, Lisp_Object domain) 606 unsigned int* width, unsigned int* height,
510 { 607 enum image_instance_geometry disp, Lisp_Object domain)
511 widget_instantiate_1 (image_instance, instantiator, pointer_fg, 608 {
512 pointer_bg, dest_mask, domain, 1, 0, 0); 609 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
513 } 610 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
514 611
515 /* tree-view generic instantiation - get the height right */ 612
516 static void 613 if (*width)
517 tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 614 {
518 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 615 /* #### what should this be. reconsider when X has tree views. */
519 int dest_mask, Lisp_Object domain) 616 query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
520 { 617 IMAGE_INSTANCE_WIDGET_FACE (ii),
521 Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), 618 width, 0, 0, domain);
522 Q_items, Qnil); 619 }
523 int len; 620 if (*height)
524 GET_LIST_LENGTH (data, len); 621 {
525 widget_instantiate_1 (image_instance, instantiator, pointer_fg, 622 int len, h;
526 pointer_bg, dest_mask, domain, len + 1, 0, 0); 623 default_face_font_info (domain, 0, 0, &h, 0, 0);
527 } 624 GET_LIST_LENGTH (items, len);
528 625 *height = len * h;
529 static void 626 }
530 tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 627 }
531 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 628
532 int dest_mask, Lisp_Object domain) 629 /* Get the geometry of a tab control. This is based on the number of
533 { 630 items and text therin in the tab control. */
534 Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), 631 static void
535 Q_items, Qnil); 632 tab_control_query_geometry (Lisp_Object image_instance,
633 unsigned int* width, unsigned int* height,
634 enum image_instance_geometry disp, Lisp_Object domain)
635 {
636 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
637 Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
536 Lisp_Object rest; 638 Lisp_Object rest;
537 int len = 0; 639 unsigned int tw = 0, th = 0;
538 640
539 LIST_LOOP (rest, data) 641 LIST_LOOP (rest, items)
540 { 642 {
541 len += 3; /* some bias */ 643 unsigned int h, w;
542 if (STRINGP (XCAR (rest))) 644
543 len += XSTRING_LENGTH (XCAR (rest)); 645 query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
544 else if (VECTORP (XCAR (rest))) 646 IMAGE_INSTANCE_WIDGET_FACE (ii),
545 { 647 &w, &h, 0, domain);
546 Lisp_Object gui = gui_parse_item_keywords (XCAR (rest)); 648 tw += 2 * WIDGET_BORDER_WIDTH; /* some bias */
547 len += XSTRING_LENGTH (XGUI_ITEM (gui)->name); 649 tw += w;
548 } 650 th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
549 } 651 }
550 652
551 widget_instantiate_1 (image_instance, instantiator, pointer_fg, 653 /* Fixup returned values depending on orientation. */
552 pointer_bg, dest_mask, domain, 0, 0, len); 654 if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
553 } 655 {
554 656 if (height) *height = tw;
555 /* Instantiate a static control */ 657 if (width) *width = th;
556 static void 658 }
557 static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 659 else
558 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 660 {
559 int dest_mask, Lisp_Object domain) 661 if (height) *height = th;
560 { 662 if (width) *width = tw;
561 widget_instantiate_1 (image_instance, instantiator, pointer_fg, 663 }
562 pointer_bg, dest_mask, domain, 0, 4, 0);
563 } 664 }
564 665
565 666
566 /***************************************************************************** 667 /*****************************************************************************
567 * widget layout * 668 * widget layout *
687 788
688 /* flip through the items to work out how much stuff we have to display */ 789 /* flip through the items to work out how much stuff we have to display */
689 LIST_LOOP (rest, items) 790 LIST_LOOP (rest, items)
690 { 791 {
691 Lisp_Object glyph = XCAR (rest); 792 Lisp_Object glyph = XCAR (rest);
692 int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); 793 int gheight = glyph_height (glyph, domain);
693 int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); 794 int gwidth = glyph_width (glyph, domain);
694 nitems ++; 795 nitems ++;
695 if (EQ (orient, Qhorizontal)) 796 if (EQ (orient, Qhorizontal))
696 { 797 {
697 maxph = max (maxph, gheight); 798 maxph = max (maxph, gheight);
698 maxpw += gwidth; 799 maxpw += gwidth;
736 837
737 children = Fcons (bglyph, children); 838 children = Fcons (bglyph, children);
738 XIMAGE_INSTANCE_XOFFSET (bglyph) = 10; /* Really, what should this be? */ 839 XIMAGE_INSTANCE_XOFFSET (bglyph) = 10; /* Really, what should this be? */
739 XIMAGE_INSTANCE_YOFFSET (bglyph) = 0; 840 XIMAGE_INSTANCE_YOFFSET (bglyph) = 0;
740 841
741 ph_adjust = (glyph_height (border, Qnil, DEFAULT_INDEX, domain) / 2); 842 ph_adjust = (glyph_height (border, domain) / 2);
742 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); 843 IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
743 } 844 }
744 845
745 /* Work out vertical spacings. */ 846 /* Work out vertical spacings. */
746 if (!ph) 847 if (!ph)
766 LIST_LOOP (rest, items) 867 LIST_LOOP (rest, items)
767 { 868 {
768 /* make sure the image is instantiated */ 869 /* make sure the image is instantiated */
769 Lisp_Object glyph = XCAR (rest); 870 Lisp_Object glyph = XCAR (rest);
770 Lisp_Object gii = glyph_image_instance (glyph, domain, ERROR_ME, 1); 871 Lisp_Object gii = glyph_image_instance (glyph, domain, ERROR_ME, 1);
771 int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); 872 int gwidth = glyph_width (glyph, domain);
772 int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); 873 int gheight = glyph_height (glyph, domain);
773 874
774 children = Fcons (gii, children); 875 children = Fcons (gii, children);
775 876
776 if (EQ (orient, Qhorizontal)) 877 if (EQ (orient, Qhorizontal))
777 { 878 {
860 961
861 /* we only do this for properties */ 962 /* we only do this for properties */
862 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget"); 963 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
863 IIFORMAT_HAS_METHOD (widget, property); 964 IIFORMAT_HAS_METHOD (widget, property);
864 IIFORMAT_HAS_METHOD (widget, set_property); 965 IIFORMAT_HAS_METHOD (widget, set_property);
966 IIFORMAT_HAS_METHOD (widget, query_geometry);
967 IIFORMAT_HAS_METHOD (widget, layout);
865 968
866 /* widget image-instantiator types - buttons */ 969 /* widget image-instantiator types - buttons */
867 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button"); 970 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
868 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget); 971 IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
869 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget); 972 IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
915 1018
916 /* tree view */ 1019 /* tree view */
917 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view"); 1020 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
918 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); 1021 IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
919 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); 1022 IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
920 IIFORMAT_HAS_METHOD (tree_view, instantiate); 1023 IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1024 IIFORMAT_HAS_METHOD (tree_view, query_geometry);
921 VALID_WIDGET_KEYWORDS (tree_view); 1025 VALID_WIDGET_KEYWORDS (tree_view);
922 VALID_GUI_KEYWORDS (tree_view); 1026 VALID_GUI_KEYWORDS (tree_view);
923 IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list); 1027 IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
924 1028
925 /* tab control */ 1029 /* tab control */
926 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control"); 1030 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
927 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box); 1031 IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
928 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); 1032 IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
929 IIFORMAT_HAS_METHOD (tab_control, instantiate); 1033 IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1034 IIFORMAT_HAS_METHOD (tab_control, query_geometry);
930 VALID_WIDGET_KEYWORDS (tab_control); 1035 VALID_WIDGET_KEYWORDS (tab_control);
931 VALID_GUI_KEYWORDS (tab_control); 1036 VALID_GUI_KEYWORDS (tab_control);
1037 IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
932 IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list); 1038 IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
933 1039
934 /* labels */ 1040 /* labels */
935 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label"); 1041 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
936 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget); 1042 IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
937 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, static); 1043 IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
938 VALID_WIDGET_KEYWORDS (label); 1044 VALID_WIDGET_KEYWORDS (label);
939 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); 1045 IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
940 1046
941 /* layout */ 1047 /* layout */
942 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout"); 1048 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");