Index: lisp/ChangeLog =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/lisp/ChangeLog,v retrieving revision 1.266.2.13.2.17 diff -u -r1.266.2.13.2.17 ChangeLog --- lisp/ChangeLog 2002/05/31 04:39:24 1.266.2.13.2.17 +++ lisp/ChangeLog 2002/06/04 01:45:21 @@ -1,3 +1,15 @@ +2002-06-03 Andy Piper + + * dialog-items.el (make-search-dialog): align various subcontrols + in visually pleasing ways, allow frame to autosize to the dialog + size. + * dialog.el (make-dialog-box): add a border inside the frame. Add + :autosize property, if t then reset the frame size appropriately + before the frame is mapped. + * gutter-items.el (set-progress-feedback-instantiator): align + various subcontrols. + * gutter-items.el (set-progress-abort-instantiator): ditto. + 2002-05-30 Andy Piper * files.el (revert-buffer-internal): don't visit Index: lisp/dialog-items.el =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/lisp/dialog-items.el,v retrieving revision 1.2 diff -u -r1.2 dialog-items.el --- lisp/dialog-items.el 2001/04/12 18:21:16 1.2 +++ lisp/dialog-items.el 2002/06/04 01:45:21 @@ -60,17 +60,18 @@ 'general :parent parent :title "Search" +:autosize t :spec (setq search-dialog (make-glyph `[layout - :orientation horizontal :justify left - ;; neither the following height/width nor the identical one - ;; below should be necessary! (see below) - :height 11 :width 40 + :orientation horizontal + :vertically-justify top + :horizontally-justify center :border [string :data "Search"] :items - ([layout :orientation vertical :justify left + ([layout :orientation vertical + :justify top ; implies left also :items ([string :data "Search for:"] [button :descriptor "Match Case" @@ -92,10 +93,12 @@ :selected (not search-dialog-direction) :callback (setq search-dialog-direction nil)] )] - [layout :orientation vertical :justify left - :items + [layout :orientation vertical + :vertically-justify top + :horizontally-justify right + :items ([edit-field :width 15 :descriptor "" :active t - :face default :initial-focus t] + :initial-focus t] [button :width 10 :descriptor "Find Next" :callback-ex (lambda (image-instance event) @@ -108,8 +111,9 @@ (isearch-dehighlight) (delete-frame (event-channel event)))])])])) - ;; neither this height/width nor the identical one above should - ;; be necessary! (in fact, if you omit the one above, the layout - ;; sizes itself correctly; but the frame as a whole doesn't use - ;; the layout's size, as it should.) -:properties '(height 11 width 40)))) + ;; These are no longer strictly necessary, but not setting a size + ;; at all yields a much more noticeable resize since the initial + ;; frame is so big. +:properties `(height ,(widget-logical-to-character-height 6) + width ,(widget-logical-to-character-width 39)) + ))) Index: lisp/dialog.el =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/lisp/dialog.el,v retrieving revision 1.4.2.2.4.1 diff -u -r1.4.2.2.4.1 dialog.el --- lisp/dialog.el 2001/10/25 17:04:10 1.4.2.2.4.1 +++ lisp/dialog.el 2002/06/04 01:45:21 @@ -195,6 +195,8 @@ The frame is made a child of this frame (defaults to the selected frame). :properties Additional properties of the frame, as well as `dialog-frame-plist'. +:autosize + If t the frame is sized to exactly fit the widgets given by :spec. --------------------------------------------------------------------------- @@ -568,6 +570,7 @@ (:parent (selected-frame)) :modal :properties + :autosize :spec) () (flet ((create-dialog-box-frame () @@ -615,6 +618,7 @@ vertical-scrollbar-visible-p nil horizontal-scrollbar-visible-p nil unsplittable t + internal-border-width 8 left ,(+ fleft (- (/ fwidth 2) (/ (* dfwidth fontw) @@ -625,6 +629,19 @@ 2))))))) (set-face-foreground 'modeline [default foreground] frame) (set-face-background 'modeline [default background] frame) + ;; resize before mapping + (when cl-autosize + (set-frame-pixel-size + frame + (image-instance-width + (glyph-image-instance cl-spec + (frame-selected-window frame))) + (image-instance-height + (glyph-image-instance cl-spec + (frame-selected-window frame))))) + ;; somehow, even though the resizing is supposed + ;; to be while the frame is not visible, a + ;; visible resize is perceptible (unless unmapped (make-frame-visible frame)) (let ((newbuf (generate-new-buffer " *dialog box*"))) (set-buffer-dedicated-frame newbuf frame) Index: lisp/gutter-items.el =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/lisp/gutter-items.el,v retrieving revision 1.2.2.1 diff -u -r1.2.2.1 gutter-items.el --- lisp/gutter-items.el 2001/10/23 08:35:21 1.2.2.1 +++ lisp/gutter-items.el 2002/06/04 01:45:21 @@ -429,8 +429,8 @@ (setq progress-glyph-height 24) (setq progress-layout-instantiator `[layout - :orientation vertical :justify left - :margin-width 4 + :orientation vertical :margin-width 4 + :horizontally-justify left :vertically-justify center :items (,progress-text-instantiator [layout :orientation horizontal @@ -447,7 +447,8 @@ (defun set-progress-abort-instantiator (&optional locale) (set-glyph-image progress-abort-glyph - `[layout :orientation vertical :justify left + `[layout :orientation vertical + :horizontally-justify left :vertically-justify center :items (,progress-text-instantiator [layout :margin-width 4 Index: src/ChangeLog =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/ChangeLog,v retrieving revision 1.290.2.15.2.24 diff -u -r1.290.2.15.2.24 ChangeLog --- src/ChangeLog 2002/05/31 04:39:29 1.290.2.15.2.24 +++ src/ChangeLog 2002/06/04 01:45:25 @@ -1,3 +1,94 @@ +2002-06-03 Andy Piper + + * frame.c (frame_conversion_internal): add conversion appropriate + for setting frame dimensions in pixels. + + * console.h (struct console_methods): add device-specific widget + layout functions. + + * emacs.c (main_1): initialize glyph vars. + + * event-Xt.c (handle_focus_event_1): call handle_focus_event_2 + (handle_focus_event_2): new function. Allow focus to + be set to a particular window and widget. + (enqueue_focus_event): new function. Create a + synthetic focus event. + (emacs_Xt_handle_magic_event): call + handle_focus_event_2. + + * frame.c (Fset_frame_pixel_height): new function. Allow + pixel-based sizing. Does the right thing on character-oriented + displays. + (Fset_frame_pixel_width): ditto. + (Fset_frame_pixel_size): ditto. + (syms_of_frame): declare. + + * general-slots.h: add :vertically-justify and + :horizontally-justify. + + * glyphs-msw.c (xbm_create_bitmap_from_data): warning fix. + (mswindows_widget_border_width): new function. + (mswindows_combo_box_instantiate): set border widths. + (console_type_create_glyphs_mswindows): declare. + + * glyphs-widget.c: + (check_valid_justification): allow vertical and horizontal + justification. + (widget_border_width): new function. Call device methods. + (widget_instance_border_width): ditto. + (logical_unit_height): new function. Determine the height of a + logical-unit. Logical units are intended to provide grid-like + layout for subcontrols in a layout. If the layout is + :vertically-justify top then subcontrols will be positioned on + logical-unit boundaries, thus allowing adjacent subcontrols to + line up. + (widget_logical_unit_height): ditto for widgets. + (redisplay_widget): misc cleanup. + (widget_spacing): new function. Call device specific + methods. Intended to be the default gap between adjacent widgets. + (widget_query_geometry): use new spacing functions to determine + appropriate geometry. + (initialize_widget_image_instance): initialize horizontal and + vertical justification. + (widget_instantiate): use logica-units where appropriate for + sizing large widgets. + (button_query_geometry): use widget_instance_border_width. + (tree_view_query_geometry): ditto. + (tab_control_query_geometry): ditto. + (edit_field_query_geometry): new function. + (layout_update): pick up :justify, :horizontally-justify and + :vertically-justify none of which worked previously. :justify is + used as a fallback for both horizontal and vertical justification. + (layout_query_geometry): use logical units to size appropriately. + (layout_layout): ditto. + (Fwidget_logical_to_character_width): new function. Allow users to + convert from logical units to characters so that frame sizes can + be set appropriately. + (Fwidget_logical_to_character_height): ditto. + (syms_of_glyphs_widget): declare. + (image_instantiator_edit_fields): add edit_field_query_geometry. + (VALID_LAYOUT_KEYWORDS): declare :vertically-justify and + :horizontally-justify. + (specifier_vars_of_glyphs_widget): new function. Declare + Vwidget_border_width which is not yet used. + + * glyphs-x.c (x_map_subwindow): enqueue appropriate focus events. + (x_widget_border_width): new function. + (x_widget_instantiate): create a sensible name for widgets. + (console_type_create_glyphs_x): declare x_widget_border_width. + + * glyphs.h (DEFAULT_WIDGET_BORDER_WIDTH): new macro. + (struct Lisp_Image_Instance): add :vertically-justify and + :horizontally-justify. + (LAYOUT_JUSTIFY_TOP): new. + (IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY): new. + (ROUND_UP): new macro. Round argument up to next integral + interval. + + * redisplay-output.c (redisplay_output_layout): misc formatting. + + * symsinit.h: declare specifier_vars_of_glyphs_widget. + 2002-05-16 Mathias Grimmberger * sysdep.c (sys_rename): Make sys_rename work for the case where Index: src/console.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/console.h,v retrieving revision 1.24.2.1 diff -u -r1.24.2.1 console.h --- src/console.h 2001/10/23 08:35:30 1.24.2.1 +++ src/console.h 2002/06/04 01:45:25 @@ -261,6 +261,11 @@ void (*resize_subwindow_method) (Lisp_Image_Instance *, int w, int h); void (*redisplay_subwindow_method) (Lisp_Image_Instance *); void (*redisplay_widget_method) (Lisp_Image_Instance *); + /* Maybe this should be a specifier. Unfortunately specifiers don't + allow us to represent things at the toolkit level, which is what + is required here. */ + int (*widget_border_width_method) (void); + int (*widget_spacing_method) (Lisp_Image_Instance *); int (*image_instance_equal_method) (Lisp_Image_Instance *, Lisp_Image_Instance *, int depth); Index: src/emacs.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/emacs.c,v retrieving revision 1.97.2.1.2.1 diff -u -r1.97.2.1.2.1 emacs.c --- src/emacs.c 2002/04/04 05:43:57 1.97.2.1.2.1 +++ src/emacs.c 2002/06/04 01:45:27 @@ -1956,6 +1956,7 @@ */ specifier_vars_of_glyphs (); + specifier_vars_of_glyphs_widget (); specifier_vars_of_gutter (); #ifdef HAVE_MENUBARS specifier_vars_of_menubar (); Index: src/event-Xt.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/event-Xt.c,v retrieving revision 1.47 diff -u -r1.47 event-Xt.c --- src/event-Xt.c 2001/04/12 18:23:40 1.47 +++ src/event-Xt.c 2002/06/04 01:45:29 @@ -68,6 +68,7 @@ #include "events-mod.h" static void handle_focus_event_1 (struct frame *f, int in_p); +static void handle_focus_event_2 (Window w, struct frame *f, int in_p); static struct event_stream *Xt_event_stream; @@ -1536,6 +1537,16 @@ static void handle_focus_event_1 (struct frame *f, int in_p) { + handle_focus_event_2 (XtWindow (FRAME_X_TEXT_WIDGET (f)), f, in_p); +} + +static void +handle_focus_event_2 (Window win, struct frame *f, int in_p) +{ + /* Although this treats focus differently for all widgets (including + the frame) it seems to work ok. */ + Widget needs_it = XtWindowToWidget (FRAME_X_DISPLAY (f), win); + #if XtSpecificationRelease > 5 widget_with_focus = XtGetKeyboardFocusWidget (FRAME_X_TEXT_WIDGET (f)); #endif @@ -1566,14 +1577,19 @@ click in the frame. Why is this? */ if (in_p #if XtSpecificationRelease > 5 - && FRAME_X_TEXT_WIDGET (f) != widget_with_focus + && needs_it != widget_with_focus #endif ) { - lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), - FRAME_X_TEXT_WIDGET (f)); + lw_set_keyboard_focus (FRAME_X_SHELL_WIDGET (f), needs_it); } + /* If we are focusing on a native widget then record and exit. */ + if (needs_it != FRAME_X_TEXT_WIDGET (f)) { + widget_with_focus = needs_it; + return; + } + /* We have the focus now. See comment in emacs_Xt_handle_widget_losing_focus (). */ if (in_p) @@ -1595,9 +1611,26 @@ } } +/* Create a synthetic X focus event. */ +void +enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p) +{ + Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); + Lisp_Event *ev = XEVENT (emacs_event); + XEvent *x_event = &ev->event.magic.underlying_x_event; + + x_event->type = in_p ? FocusIn : FocusOut; + x_event->xfocus.window = XtWindow (wants_it); + + ev->channel = frame; + ev->event_type = magic_event; + + enqueue_Xt_dispatch_event (emacs_event); +} + /* The idea here is that when a widget glyph gets unmapped we don't want the focus to stay with it if it has focus - because it may - well just get deleted next andthen we have lost the focus until the + well just get deleted next and then we have lost the focus until the user does something. So handle_focus_event_1 records the widget with keyboard focus when FocusOut is processed, and then, when a widget gets unmapped, it calls this function to restore focus if @@ -1924,7 +1957,7 @@ if (FRAME_X_EXTERNAL_WINDOW_P (f)) break; #endif - handle_focus_event_1 (f, event->type == FocusIn); + handle_focus_event_2 (event->xfocus.window, f, event->type == FocusIn); break; case ClientMessage: Index: src/frame.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/frame.c,v retrieving revision 1.40.2.1 diff -u -r1.40.2.1 frame.c --- src/frame.c 2001/10/23 08:35:33 1.40.2.1 +++ src/frame.c 2002/06/04 01:45:31 @@ -116,6 +116,10 @@ Lisp_Object Qframe_being_created; static void store_minibuf_frame_prop (struct frame *f, Lisp_Object val); +static void frame_conversion_internal (struct frame *f, int pixel_to_char, + int *pixel_width, int *pixel_height, + int *char_width, int *char_height, + int real_face); static struct display_line title_string_display_line; /* Used by generate_title_string. Global because they get used so much that the dynamic allocation time adds up. */ @@ -2623,6 +2627,37 @@ return frame; } +DEFUN ("set-frame-pixel-height", Fset_frame_pixel_height, 2, 3, 0, /* +Specify that the frame FRAME is HEIGHT pixels tall. +Optional third arg non-nil means that redisplay should be HEIGHT pixels tall +but that the idea of the actual height of the frame should not be changed. +*/ + (frame, height, pretend)) +{ + struct frame *f = decode_frame (frame); + int pheight, width; + XSETFRAME (frame, f); + CHECK_INT (height); + + if (!window_system_pixelated_geometry (frame)) + { + int h = XINT (height); + width = FRAME_WIDTH (f); + /* Simply using pixel_to_real_char_size here is not good + enough since we end up with a total frame size of HEIGHT + rather than a displayable height of HEIGHT. */ + frame_conversion_internal (f, 2, 0, &h, 0, &pheight, 0); + } + else + { + width = FRAME_PIXWIDTH (f); + pheight = XINT (height); + } + + internal_set_frame_size (f, width, pheight, !NILP (pretend)); + return frame; +} + DEFUN ("set-frame-width", Fset_frame_width, 2, 3, 0, /* Specify that the frame FRAME has COLS columns. Optional third arg non-nil means that redisplay should use COLS columns @@ -2650,6 +2685,37 @@ return frame; } +DEFUN ("set-frame-pixel-width", Fset_frame_pixel_width, 2, 3, 0, /* +Specify that the frame FRAME is WIDTH pixels wide. +Optional third arg non-nil means that redisplay should be WIDTH wide +but that the idea of the actual height of the frame should not be changed. +*/ + (frame, width, pretend)) +{ + struct frame *f = decode_frame (frame); + int height, pwidth; + XSETFRAME (frame, f); + CHECK_INT (width); + + if (!window_system_pixelated_geometry (frame)) + { + int w = XINT (width); + height = FRAME_HEIGHT (f); + /* Simply using pixel_to_real_char_size here is not good + enough since we end up with a total frame size of WIDTH + rather than a displayable height of WIDTH. */ + frame_conversion_internal (f, 2, &w, 0, &pwidth, 0, 0); + } + else + { + height = FRAME_PIXHEIGHT (f); + pwidth = XINT (width); + } + + internal_set_frame_size (f, pwidth, height, !NILP (pretend)); + return frame; +} + DEFUN ("set-frame-size", Fset_frame_size, 3, 4, 0, /* Set the size of FRAME to COLS by ROWS, measured in characters. Optional fourth arg non-nil means that redisplay should use COLS by ROWS @@ -2675,6 +2741,38 @@ return frame; } +DEFUN ("set-frame-pixel-size", Fset_frame_pixel_size, 3, 4, 0, /* +Set the size of FRAME to WIDTH by HEIGHT, measured in pixels. +Optional fourth arg non-nil means that redisplay should use WIDTH by HEIGHT +but that the idea of the actual size of the frame should not be changed. +*/ + (frame, width, height, pretend)) +{ + struct frame *f = decode_frame (frame); + int pheight, pwidth; + XSETFRAME (frame, f); + CHECK_INT (width); + CHECK_INT (height); + + if (!window_system_pixelated_geometry (frame)) + { + int w = XINT (width); + int h = XINT (height); + /* Simply using pixel_to_real_char_size here is not good enough + since we end up with a total frame size of WIDTH x HEIGHT + rather than a displayable height of WIDTH x HEIGHT. */ + frame_conversion_internal (f, 2, &w, &h, &pwidth, &pheight, 0); + } + else + { + pheight = XINT (height); + pwidth = XINT (width); + } + + internal_set_frame_size (f, pwidth, pheight, !NILP (pretend)); + return frame; +} + DEFUN ("set-frame-position", Fset_frame_position, 3, 3, 0, /* Set position of FRAME in pixels to XOFFSET by YOFFSET. This is actually the position of the upper left corner of the frame. @@ -2730,8 +2828,22 @@ FRAME_THEORETICAL_BOTTOM_TOOLBAR_HEIGHT (f) + 2 * FRAME_THEORETICAL_TOP_TOOLBAR_BORDER_WIDTH (f) + 2 * FRAME_THEORETICAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f); + + /* Convert to chars so that the displayable area is pixel_width x + pixel_height. - if (pixel_to_char) + #### Consider rounding up to 0.5 characters to avoid adding too + much space. */ + if (pixel_to_char > 1) + { + if (char_width) + *char_width = ROUND_UP (*pixel_width, cpw) / cpw; + if (char_height) + *char_height = ROUND_UP (*pixel_height, cph) / cph; + } + /* Convert to chars so that the total frame size is pixel_width x + pixel_height. */ + else if (pixel_to_char) { if (char_width) *char_width = 1 + ((*pixel_width - egw) - bdr - obw) / cpw; @@ -3293,6 +3405,9 @@ DEFSUBR (Fset_frame_height); DEFSUBR (Fset_frame_width); DEFSUBR (Fset_frame_size); + DEFSUBR (Fset_frame_pixel_height); + DEFSUBR (Fset_frame_pixel_width); + DEFSUBR (Fset_frame_pixel_size); DEFSUBR (Fset_frame_position); DEFSUBR (Fset_frame_pointer); DEFSUBR (Fprint_job_page_number); Index: src/general-slots.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/general-slots.h,v retrieving revision 1.2.2.1.4.1 diff -u -r1.2.2.1.4.1 general-slots.h --- src/general-slots.h 2001/10/25 17:04:16 1.2.2.1.4.1 +++ src/general-slots.h 2002/06/04 01:45:31 @@ -139,6 +139,8 @@ SYMBOL (Qinternal); SYMBOL_KEYWORD (Q_items); SYMBOL_KEYWORD (Q_justify); +SYMBOL_KEYWORD (Q_vertically_justify); +SYMBOL_KEYWORD (Q_horizontally_justify); SYMBOL (Qkey); SYMBOL (Qkey_assoc); SYMBOL_KEYWORD (Q_key_sequence); Index: src/glyphs-msw.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/glyphs-msw.c,v retrieving revision 1.28.2.1.2.2 diff -u -r1.28.2.1.2.2 glyphs-msw.c --- src/glyphs-msw.c 2002/05/04 20:23:28 1.28.2.1.2.2 +++ src/glyphs-msw.c 2002/06/04 01:45:33 @@ -1720,9 +1720,9 @@ for (j=0; j> 4]); + ((flip_table[bite & 0xf] << 4) + flip_table[bite >> 4]); } } @@ -2368,6 +2368,13 @@ } } +/* Account for some of the limitations with widget images. */ +static int +mswindows_widget_border_width (void) +{ + return DEFAULT_WIDGET_BORDER_WIDTH; +} + /* register widgets into our hashtable so that we can cope with the callbacks. The hashtable is weak so deregistration is handled automatically */ @@ -3078,7 +3085,7 @@ default_face_font_info (domain, 0, 0, &height, 0, 0); GET_LIST_LENGTH (items, len); - height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len; + height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len; IMAGE_INSTANCE_HEIGHT (ii) = height; /* Now create the widget. */ @@ -3236,6 +3243,7 @@ CONSOLE_HAS_METHOD (mswindows, image_instance_hash); CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage); CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file); + CONSOLE_HAS_METHOD (mswindows, widget_border_width); /* image methods - printer */ CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_image_instance); Index: src/glyphs-widget.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/glyphs-widget.c,v retrieving revision 1.2 diff -u -r1.2 glyphs-widget.c --- src/glyphs-widget.c 2001/04/12 18:23:51 1.2 +++ src/glyphs-widget.c 2002/06/04 01:45:33 @@ -1,5 +1,5 @@ /* Widget-specific glyph objects. - Copyright (C) 1998, 1999, 2000 Andy Piper. + Copyright (C) 1998, 1999, 2000, 2002 Andy Piper. This file is part of XEmacs. @@ -60,7 +60,13 @@ Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; Lisp_Object Qmake_glyph; +Lisp_Object Vwidget_border_width; +static int +widget_border_width (Lisp_Object domain); +static int +widget_spacing (Lisp_Object domain); + #ifdef DEBUG_WIDGETS int debug_widget_instances; #endif @@ -118,7 +124,15 @@ static void check_valid_justification (Lisp_Object data) { - if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter)) + if (!EQ (data, Qleft) + && + !EQ (data, Qright) + && + !EQ (data, Qtop) + && + !EQ (data, Qbottom) + && + !EQ (data, Qcenter)) invalid_argument ("unknown justification for layout", data); } @@ -238,6 +252,54 @@ } } +/* Determine the border with of the widget. */ +static int +widget_border_width (Lisp_Object domain) +{ + /* #### FIXME -- need to use specifiers (Vwidget_border_width) for + some portion of this. */ + if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), + widget_border_width)) + return DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ()); + else + return DEFAULT_WIDGET_BORDER_WIDTH; +} + +static int +widget_instance_border_width (Lisp_Image_Instance* ii) +{ + return widget_border_width (IMAGE_INSTANCE_DOMAIN (ii)); +} + +/* #### Its not clear to me what the value of logical_unit_height should + be, or whether it should even depend on the current + image_instance. It really should probably only depend on the + default widget face and the domain, however you can envisage users + wanting different logical units for nested layouts - so using the + properties of the current lahyout is probably not so dumb. */ +static int +logical_unit_height (Lisp_Object text, Lisp_Object face, Lisp_Object domain) +{ + int charheight = 0; + query_string_geometry (text, face, + 0, &charheight, 0, domain); + /* For the returned value to be useful it needs to be big enough to + accomodate the largest single-height widget. This is currently + the edit-field. */ + return charheight + 2 * widget_spacing (domain) + + 4 * widget_border_width (domain); +} + +static int +widget_logical_unit_height (Lisp_Image_Instance* ii) +{ + return logical_unit_height (NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)) ? + IMAGE_INSTANCE_NAME (ii) + : IMAGE_INSTANCE_WIDGET_TEXT (ii), + IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_DOMAIN (ii)); +} + /* Wire widget property invocations to specific widgets. The problem we are solving here is that when instantiators get converted to instances they lose some type information (they just become @@ -424,7 +486,8 @@ from lisp does not result in synchronous updates. Do this last so that format-specific methods have an opportunity to prevent wholesale changes - e.g. rebuilding tabs. */ - MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii)); + MAYBE_DEVMETH (DOMAIN_XDEVICE (IMAGE_INSTANCE_DOMAIN (ii)), + redisplay_widget, (ii)); /* Pick up the items we recorded earlier. */ if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) @@ -435,6 +498,17 @@ } } +/* Determine the spacing of the widget. */ +static int +widget_spacing (Lisp_Object domain) +{ + if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_spacing)) + return DEVMETH (DOMAIN_XDEVICE (domain), + widget_spacing, (0)); + else + return DEFAULT_WIDGET_SPACING; +} + /* Query for a widgets desired geometry. If no type specific method is provided then use the widget text to calculate sizes. */ static void @@ -483,9 +557,9 @@ &w, &h, 0, domain); /* Adjust the size for borders. */ if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) - *width = w + 2 * WIDGET_BORDER_WIDTH; + *width = w + 2 * widget_instance_border_width (ii); if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) - *height = h + 2 * WIDGET_BORDER_HEIGHT; + *height = h + 2 * widget_instance_border_width (ii); } } /* Finish off with dynamic sizing. */ @@ -597,7 +671,8 @@ IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL; - IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = 0; } /* Instantiate a button widget. Unfortunately instantiated widgets are @@ -715,24 +790,44 @@ size in characters is probably as good as any since the widget face is more likely to be proportional and thus give inadequate results. Using character sizes can only ever be approximate - anyway. */ - if (tw || th) + anyway. :height is measured in logical characters which take into + account the borders and spacing on widgets. */ + if (tw) + { + int charwidth; + default_face_font_info (domain, 0, 0, 0, &charwidth, 0); + pw = ROUND_UP (charwidth * tw + 4 * widget_instance_border_width (ii), charwidth); + } + + /* For heights the widget face is more appropriate. */ + if (th == 1) + { + int charheight; + if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) + { + query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), + IMAGE_INSTANCE_WIDGET_FACE (ii), + 0, &charheight, 0, domain); + } + else + { + default_face_font_info (domain, 0, 0, &charheight, 0, 0); + } + ph = (charheight + 2 * widget_instance_border_width (ii)) * th; + } + /* For heights > 1 use logical units. */ + else if (th > 1) { - int charwidth, charheight; - default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0); - if (tw) - pw = charwidth * tw; - if (th) - ph = charheight * th; + ph = widget_logical_unit_height (ii) * th; } /* for a widget with an image pick up the dimensions from that */ if (!NILP (glyph)) { if (!pw) - pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH; + pw = glyph_width (glyph, image_instance) + 2 * widget_instance_border_width (ii); if (!ph) - ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT; + ph = glyph_height (glyph, image_instance) + 2 * widget_instance_border_width (ii); IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; } @@ -779,7 +874,7 @@ /* Adjust the size for borders. */ if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) { - *width = w + 2 * WIDGET_BORDER_WIDTH; + *width = w + 3 * widget_instance_border_width (ii); if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio) || @@ -787,8 +882,26 @@ /* This is an approximation to the size of the actual button bit. */ *width += 12; } + if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) + *height = h + 3 * widget_instance_border_width (ii); +} + +/* Get the geometry of an edit field. */ +static void +edit_field_query_geometry (Lisp_Object image_instance, + int* width, int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + int w, h; + query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii), + IMAGE_INSTANCE_WIDGET_FACE (ii), + &w, &h, 0, domain); + /* Adjust the size for borders. */ + if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) + *width = w + 4 * widget_instance_border_width (ii); if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) - *height = h + 2 * WIDGET_BORDER_HEIGHT; + *height = h + 4 * widget_instance_border_width (ii); } /* tree-view geometry - get the height right */ @@ -811,6 +924,7 @@ if (*height) { int len, h; + /* #### widget face would be better here. */ default_face_font_info (domain, 0, 0, &h, 0, 0); GET_LIST_LENGTH (items, len); *height = len * h; @@ -836,9 +950,9 @@ query_string_geometry (XGUI_ITEM (XCAR (rest))->name, IMAGE_INSTANCE_WIDGET_FACE (ii), &w, &h, 0, domain); - tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */ + tw += 5 * widget_instance_border_width (ii); /* some bias */ tw += w; - th = max (th, h + 2 * WIDGET_BORDER_HEIGHT); + th = max (th, h + 2 * widget_instance_border_width (ii)); } /* Fixup returned values depending on orientation. */ @@ -948,14 +1062,50 @@ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border); + Lisp_Object justify = find_keyword_in_vector (instantiator, Q_justify); + Lisp_Object hjustify = find_keyword_in_vector (instantiator, Q_horizontally_justify); + Lisp_Object vjustify = find_keyword_in_vector (instantiator, Q_vertically_justify); Lisp_Object border = Qnil; Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii); int structure_changed = 0; struct gcpro gcpro1; + /* Pick up horizontal justification, left is the default.*/ + if (!NILP (hjustify)) + { + if (EQ (hjustify, Qright) || EQ (hjustify, Qbottom)) + IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT; + else if (EQ (hjustify, Qcenter)) + IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; + } + /* If not set use general justification. */ + else if (!NILP (justify)) + { + if (EQ (justify, Qright) || EQ (justify, Qbottom)) + IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_RIGHT; + else if (EQ (justify, Qcenter)) + IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; + } + + /* Pick up vertical justification, top is the default. */ + if (!NILP (vjustify)) + { + if (EQ (vjustify, Qright) || EQ (vjustify, Qbottom)) + IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM; + else if (EQ (vjustify, Qcenter)) + IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; + } + /* If not set use general justification. */ + else if (!NILP (justify)) + { + if (EQ (justify, Qright) || EQ (justify, Qbottom)) + IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_BOTTOM; + else if (EQ (justify, Qcenter)) + IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY (ii) = LAYOUT_JUSTIFY_CENTER; + } + /* We want to avoid consing if we can. This is quite awkward because we have to deal with the border as well as the items. */ - GCPRO1 (border); if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) @@ -1107,7 +1257,30 @@ glyphs are cached on a device basis like most other glyphs. Instead they should be cached per-window and then the instance would be fixed and we wouldn't have to mess around with font metrics and the - rest. */ + rest. + + Another sizing problem is alignment. We provide layout widgets that + allow users to stack widgets vertically or horizontally. These + layouts also allow the widgets to be centered (space evenly + distributed), left or right justified (fixed spacing widgets + stacked against the left, righ, top or bottom edge). Unfortunately + this doesn't allow widgets in different layouts to be aligned. For + instance how should the search dialog be organized for alignment? + The obvious choice of two vertical columns does not work since the + size of individual widgets will affect where they get placed. The + same is true for several rows of widgets. To solve this problem we + introduce the notion of `logical_unit_height'. This is a size + quantity that is designed to be big enough to accomodate the + largest `single height unit'. The function + widget_logical_unit_height() determines the value of this in + pixels. It is dependent on the widget face and some combination of + spacing and border-width. Thus if users specify left or right + justification in a vertical layout they get something in logical + units. To simplify this the functions + `widget-logical-to-character-height' and + `widget-logical-to-character-width' allow conversion between + characters and logical units so that frames can be sized + appropriately. */ /* Query the geometry of a layout widget. We assume that we can only get here if the size is not already fixed. */ @@ -1119,7 +1292,7 @@ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest; int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0; - int gheight, gwidth; + int gheight, gwidth, luh; /* If we are not initialized then we won't have any children. */ if (!IMAGE_INSTANCE_INITIALIZED (ii)) @@ -1135,12 +1308,14 @@ !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) return; + luh = widget_logical_unit_height (ii); + /* Pick up the border text if we have one. */ if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) { glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp, image_instance); - ph_adjust = gheight / 2; + ph_adjust = gheight; items = XCDR (items); } @@ -1151,8 +1326,7 @@ glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance); nitems ++; - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) { maxph = max (maxph, gheight); maxpw += gwidth; @@ -1173,13 +1347,16 @@ if (INTP (dynamic_width)) *width = XINT (dynamic_width); } - else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH + - IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2; + else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) + { + *width = maxpw + ((nitems + 1) * widget_instance_border_width (ii) + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2; + } else - *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 + - IMAGE_INSTANCE_MARGIN_WIDTH (ii)); + { + *width = maxpw + 2 * (widget_instance_border_width (ii) * 2 + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)); + } /* Work out vertical spacings. */ if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) @@ -1189,13 +1366,23 @@ if (INTP (dynamic_height)) *height = XINT (dynamic_height); } - else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_VERTICAL) - *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT + - IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; + else if (IMAGE_INSTANCE_SUBWINDOW_LOGICAL_LAYOUT (ii)) + { + *height = nitems * luh + ph_adjust; + } + else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL) + { + *height = maxph + ((nitems + 1) * widget_instance_border_width (ii) + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; + } else - *height = maxph + (2 * WIDGET_BORDER_HEIGHT + - IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; + { + *height = maxph + (2 * widget_instance_border_width (ii) + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; + } +#ifdef DEBUG_WIDGET_OUTPUT + stderr_out ("layout wants %dx%d\n", *width, *height); +#endif } int @@ -1209,20 +1396,34 @@ int x, y, maxph = 0, maxpw = 0, nitems = 0, horiz_spacing, vert_spacing, ph_adjust = 0; int gheight, gwidth; + /* See comments in widget_logical_unit_height(). */ + int luh = widget_logical_unit_height (ii); /* If we are not initialized then we won't have any children. */ if (!IMAGE_INSTANCE_INITIALIZED (ii)) return 0; - /* Pick up the border text if we have one. */ +#ifdef DEBUG_WIDGET_OUTPUT + stderr_out ("layout output %dx%d\n", width, height); +#endif + + /* Pick up the border text if we have one. A border can have the + values Qetched_in, Qetched_out, Qbevel_in, Qbevel_out or an + integer. The first four just affect the display properties of the + border that is drawn. The last is an offset and implies that the + first item in the list of subcontrols is a text control that + should be displayed on the border. */ if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) { Lisp_Object border = XCAR (items); items = XCDR (items); glyph_query_geometry (border, &gwidth, &gheight, IMAGE_DESIRED_GEOMETRY, image_instance); - ph_adjust = gheight / 2; - IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); + /* The vertical offset for subsequent items is the full height + of the border glyph. */ + ph_adjust = gheight; + /* The offset for the border is half the glyph height. */ + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (gheight / 2); /* #### Really, what should this be? */ glyph_do_layout (border, gwidth, gheight, 10, 0, @@ -1254,10 +1455,10 @@ if (width < maxpw) /* The user wants a smaller space than the largest item, so we just provide default spacing and will let the output routines - clip.. */ - horiz_spacing = WIDGET_BORDER_WIDTH * 2; + clip. */ + horiz_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)); else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) + == LAYOUT_HORIZONTAL) /* We have a larger area to display in so distribute the space evenly. */ horiz_spacing = (width - (maxpw + @@ -1267,18 +1468,30 @@ horiz_spacing = (width - maxpw) / 2 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); + /* We are trying here to get widgets to line up when they are left + or right justified vertically. This means that we must position + widgets on logical unit boundaries, even though their height may + be greater or less than a logical unit. In order to avoid + clipping we need to determine how big the widget wants to be and + then allocate as many logical units as necessary in order to + accommodate it. */ if (height < maxph) - vert_spacing = WIDGET_BORDER_HEIGHT * 2; + vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2; else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL) - vert_spacing = (height - (maxph + ph_adjust + - IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) - / (nitems + 1); + { + if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) + vert_spacing = widget_spacing (IMAGE_INSTANCE_DOMAIN (ii)) * 2; + else + vert_spacing = (height - (maxph + ph_adjust + + IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) + / (nitems + 1); + } else vert_spacing = (height - (maxph + ph_adjust)) / 2 - IMAGE_INSTANCE_MARGIN_WIDTH (ii); - y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii); + y = yoffset = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii); x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii); /* Now flip through putting items where we want them, paying @@ -1291,37 +1504,37 @@ glyph_query_geometry (glyph, &gwidth, &gheight, IMAGE_DESIRED_GEOMETRY, image_instance); - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) { - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_RIGHT) + if (IMAGE_INSTANCE_SUBWINDOW_BOTTOM_JUSTIFIED (ii)) y = height - (gheight + vert_spacing); - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_CENTER) + else if (IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) y = (height - gheight) / 2; } else { - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_RIGHT) + if (IMAGE_INSTANCE_SUBWINDOW_RIGHT_JUSTIFIED (ii)) x = width - (gwidth + horiz_spacing); - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_CENTER) + else if (IMAGE_INSTANCE_SUBWINDOW_H_CENTERED (ii)) x = (width - gwidth) / 2; } /* Now layout subwidgets if they require it. */ glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance); - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_HORIZONTAL) { x += (gwidth + horiz_spacing); } else { y += (gheight + vert_spacing); + if (!IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (ii)) + { + /* justified, vertical layout, try and align on logical unit + boundaries. */ + y = ROUND_UP (y - yoffset, luh) + yoffset; + } } } @@ -1386,6 +1599,67 @@ return 1; } +DEFUN ("widget-logical-to-character-width", Fwidget_logical_to_character_width, 1, 3, 0, /* +Convert the width in logical widget units to characters. +Logical widget units do not take into account adjusments made for +layout borders, so this adjusment is approximated. +*/ + (width, face, domain)) +{ + int w, neww, charwidth; + int border_width = DEFAULT_WIDGET_BORDER_WIDTH; + + if (NILP (domain)) + domain = Fselected_frame (Qnil); + + CHECK_INT (width); + w = XINT (width); + + if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_border_width)) + border_width = DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ()); + + default_face_font_info (domain, 0, 0, 0, &charwidth, 0); + neww = ROUND_UP (charwidth * w + 4 * border_width + 2 * widget_spacing (domain), + charwidth) / charwidth; + + return make_int (neww); +} + +DEFUN ("widget-logical-to-character-height", Fwidget_logical_to_character_height, 1, 3, 0, /* +Convert the height in logical widget units to characters. +Logical widget units do not take into account adjusments made for +layout borders, so this adjustment is approximated. + +If the components of a widget layout are justified to the top or the +bottom then they are aligned in terms of `logical units'. This is a +size quantity that is designed to be big enough to accomodate the +largest `single height' widget. It is dependent on the widget face and +some combination of spacing and border-width. Thus if you specify top +or bottom justification in a vertical layout the subcontrols are laid +out one per logical unit. This allows adjoining layouts to have +identical alignment for their subcontrols. + +Since frame sizes are measured in characters, this function allows you +to do appropriate conversion between logical units and characters. +*/ + (height, face, domain)) +{ + int h, newh, charheight; + + CHECK_INT (height); + if (NILP (domain)) + domain = Fselected_frame (Qnil); + + h = XINT (height); + + default_face_font_info (domain, 0, 0, &charheight, 0, 0); + newh = ROUND_UP (logical_unit_height (Fsymbol_name (Qwidget), + Vwidget_face, domain) * h, charheight) + / charheight; + + return make_int (newh); +} + /************************************************************************/ /* initialization */ @@ -1399,6 +1673,9 @@ DEFSYMBOL (Qbevel_in); DEFSYMBOL (Qbevel_out); DEFSYMBOL (Qmake_glyph); + + DEFSUBR (Fwidget_logical_to_character_height); + DEFSUBR (Fwidget_logical_to_character_width); } #define VALID_GUI_KEYWORDS(type) do { \ @@ -1462,6 +1739,7 @@ IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget); IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget); IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow); + IIFORMAT_HAS_METHOD (edit_field, query_geometry); VALID_WIDGET_KEYWORDS (edit_field); VALID_GUI_KEYWORDS (edit_field); } @@ -1559,6 +1837,8 @@ VALID_WIDGET_KEYWORDS (layout); \ IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \ IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); \ + IIFORMAT_VALID_KEYWORD (layout, Q_vertically_justify, check_valid_justification); \ + IIFORMAT_VALID_KEYWORD (layout, Q_horizontally_justify, check_valid_justification); \ IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); \ IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \ IIFORMAT_VALID_KEYWORD (layout, Q_items, \ @@ -1626,4 +1906,16 @@ vars_of_glyphs_widget (void) { reinit_vars_of_glyphs_widget (); +} + + +void +specifier_vars_of_glyphs_widget (void) +{ + DEFVAR_SPECIFIER ("widget-border-width", + &Vwidget_border_width /* +*Border width of widgets. +This is a specifier; use `set-specifier' to change it. +*/ ); + Vwidget_border_width = Fmake_specifier (Qnatnum); } Index: src/glyphs-x.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/glyphs-x.c,v retrieving revision 1.54.2.1 diff -u -r1.54.2.1 glyphs-x.c --- src/glyphs-x.c 2001/10/23 08:35:34 1.54.2.1 +++ src/glyphs-x.c 2002/06/04 01:45:35 @@ -4,7 +4,7 @@ Copyright (C) 1995 Tinker Systems Copyright (C) 1995, 1996 Ben Wing Copyright (C) 1995 Sun Microsystems - Copyright (C) 1999, 2000 Andy Piper + Copyright (C) 1999, 2000, 2002 Andy Piper This file is part of XEmacs. @@ -158,6 +158,8 @@ #endif void emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget); +void +enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p); #include "bitmaps.h" @@ -2171,6 +2173,14 @@ -dga->xoffset, -dga->yoffset); if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); + /* See comments in glyphs-msw.c about keyboard focus. */ + if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p)) { + /* #### FIXME to pop-up the find dialog we map the text-field + seven times! This doesn't show on a fast linux box but does + under X on windows. */ + enqueue_focus_event (IMAGE_INSTANCE_X_WIDGET_ID (p), + IMAGE_INSTANCE_FRAME (p), 1); + } } } @@ -2345,6 +2355,14 @@ IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win; } +/* Account for some of the limitations with widget images. */ +static int +x_widget_border_width (void) +{ + return DEFAULT_WIDGET_BORDER_WIDTH * 2; +} + + #if 0 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */ DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /* @@ -2507,6 +2525,10 @@ free_widget_value_tree (clip_wv); + /* create a sensible name. */ + if (wv->name == 0 || strcmp(wv->name, "") == 0) + wv->name = xstrdup (type); + /* copy any args we were given */ ac = 0; lw_add_value_args_to_args (wv, al, &ac); @@ -2882,6 +2904,7 @@ CONSOLE_HAS_METHOD (x, map_subwindow); CONSOLE_HAS_METHOD (x, redisplay_widget); CONSOLE_HAS_METHOD (x, redisplay_subwindow); + CONSOLE_HAS_METHOD (x, widget_border_width); } void Index: src/glyphs.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/glyphs.h,v retrieving revision 1.20 diff -u -r1.20 glyphs.h --- src/glyphs.h 2001/04/12 18:23:53 1.20 +++ src/glyphs.h 2002/06/04 01:45:36 @@ -97,8 +97,9 @@ #define IMAGE_UNSPECIFIED_GEOMETRY -1 #define IMAGE_UNCHANGED_GEOMETRY -2 -#define WIDGET_BORDER_HEIGHT 4 -#define WIDGET_BORDER_WIDTH 4 +#define DEFAULT_WIDGET_BORDER_WIDTH 2 +#define DEFAULT_WIDGET_SPACING 3 +#define DEFAULT_WIDGET_SHADOW_WIDTH 2 enum governing_domain { @@ -587,7 +588,8 @@ unsigned int v_resize : 1; /* Whether the vsize is allowed to change. */ unsigned int h_resize : 1; /* Whether the hsize is allowed to change. */ unsigned int orientation : 1; /* Vertical or horizontal. */ - unsigned int justification : 2; /* Left, right or center. */ + unsigned int h_justification : 2; /* left, right or center. */ + unsigned int v_justification : 2; /* top, bottom or center. */ /* Face for colors and font. We specify this here because we want people to be able to put :face in the instantiator spec. Using glyph-face is more inconvenient, although more @@ -616,7 +618,9 @@ #define LAYOUT_VERTICAL 1 #define LAYOUT_JUSTIFY_LEFT 0 +#define LAYOUT_JUSTIFY_TOP 0 #define LAYOUT_JUSTIFY_RIGHT 1 +#define LAYOUT_JUSTIFY_BOTTOM 1 #define LAYOUT_JUSTIFY_CENTER 2 #define IMAGE_INSTANCE_HASH_DEPTH 0 @@ -708,8 +712,26 @@ ((i)->u.subwindow.h_resize) #define IMAGE_INSTANCE_SUBWINDOW_ORIENT(i) \ ((i)->u.subwindow.orientation) -#define IMAGE_INSTANCE_SUBWINDOW_JUSTIFY(i) \ -((i)->u.subwindow.justification) +#define IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY(i) \ +((i)->u.subwindow.h_justification) +#define IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY(i) \ +((i)->u.subwindow.v_justification) +#define IMAGE_INSTANCE_SUBWINDOW_RIGHT_JUSTIFIED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY(i) == LAYOUT_JUSTIFY_RIGHT) +#define IMAGE_INSTANCE_SUBWINDOW_LEFT_JUSTIFIED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY(i) == LAYOUT_JUSTIFY_LEFT) +#define IMAGE_INSTANCE_SUBWINDOW_TOP_JUSTIFIED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY(i) == LAYOUT_JUSTIFY_TOP) +#define IMAGE_INSTANCE_SUBWINDOW_BOTTOM_JUSTIFIED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY(i) == LAYOUT_JUSTIFY_BOTTOM) +#define IMAGE_INSTANCE_SUBWINDOW_H_CENTERED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_H_JUSTIFY(i) == LAYOUT_JUSTIFY_CENTER) +#define IMAGE_INSTANCE_SUBWINDOW_V_CENTERED(i) \ + (IMAGE_INSTANCE_SUBWINDOW_V_JUSTIFY(i) == LAYOUT_JUSTIFY_CENTER) +#define IMAGE_INSTANCE_SUBWINDOW_LOGICAL_LAYOUT(i) \ + (IMAGE_INSTANCE_SUBWINDOW_ORIENT (i) \ + == LAYOUT_VERTICAL && !IMAGE_INSTANCE_SUBWINDOW_V_CENTERED (i)) + #define IMAGE_INSTANCE_SUBWINDOW_FACE(i) \ ((i)->u.subwindow.face) @@ -1147,5 +1169,7 @@ int check_for_ignored_expose (struct frame* f, int x, int y, int width, int height); extern int hold_ignored_expose_registration; + +#define ROUND_UP(arg, unit) (((int)((arg) + (unit) - 1) / (int)(unit)) * (int)(unit)) #endif /* INCLUDED_glyphs_h_ */ Index: src/redisplay-output.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-output.c,v retrieving revision 1.12.2.1.2.1 diff -u -r1.12.2.1.2.1 redisplay-output.c --- src/redisplay-output.c 2002/04/23 18:20:13 1.12.2.1.2.1 +++ src/redisplay-output.c 2002/06/04 01:45:37 @@ -2,7 +2,7 @@ Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 1996 Ben Wing. Copyright (C) 1996 Chuck Thompson. - Copyright (C) 1999 Andy Piper. + Copyright (C) 1999, 2002 Andy Piper. This file is part of XEmacs. @@ -1353,17 +1353,22 @@ int edges = 0; enum edge_style style; int ypos = db->ypos; + int xpos = db->xpos; int height = dga->height; + int width = dga->width; - if (dga->xoffset >= 0) + /* The bevel_area routines always draw in from the specified + area so there is no need to adjust the displayed area to + make sure that the lines are visible. */ + if (dga->xoffset >= 0) edges |= EDGE_LEFT; - if (dga->width - dga->xoffset == layout_width) + if (dga->width - dga->xoffset == layout_width) edges |= EDGE_RIGHT; - if (dga->yoffset >= 0) + if (dga->yoffset >= 0) edges |= EDGE_TOP; if (dga->height - dga->yoffset == layout_height) edges |= EDGE_BOTTOM; - + if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in)) style = EDGE_ETCHED_IN; else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out)) @@ -1383,9 +1388,8 @@ style = EDGE_BEVEL_OUT; MAYBE_DEVMETH (d, bevel_area, - (w, findex, db->xpos, - ypos, - dga->width, height, 2, edges, style)); + (w, findex, xpos, ypos, width, height, + DEFAULT_WIDGET_SHADOW_WIDTH, edges, style)); } } Index: src/symsinit.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/symsinit.h,v retrieving revision 1.35.2.1 diff -u -r1.35.2.1 symsinit.h --- src/symsinit.h 2001/10/23 08:35:39 1.35.2.1 +++ src/symsinit.h 2002/06/04 01:45:38 @@ -388,6 +388,7 @@ /* Initialize specifier variables (dump-time only). */ void specifier_vars_of_glyphs (void); +void specifier_vars_of_glyphs_widget (void); void specifier_vars_of_gutter (void); void specifier_vars_of_menubar (void); void specifier_vars_of_redisplay (void); Index: tests/gutter-test.el =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/tests/gutter-test.el,v retrieving revision 1.2 diff -u -r1.2 gutter-test.el --- tests/gutter-test.el 2001/04/12 18:24:47 1.2 +++ tests/gutter-test.el 2002/06/04 01:45:38 @@ -21,10 +21,10 @@ (set-gutter-element bottom-gutter 'str (make-glyph - [layout :orientation vertical - :justify left :margin-width 4 + [layout :orientation vertical :margin-width 4 + :vertically-justify center :horizontally-justify left :items ([string :data "Fontifying glyphs.c..."] - [layout :orientation horizontal + [layout :orientation horizontal :items ([progress-gauge :value 0 :pixel-height 24 :pixel-width 250 :descriptor @@ -33,7 +33,7 @@ :descriptor " Stop " :callback (quote quit)])])])) -(set-gutter-element bottom-gutter 'str2 str2) (set-gutter-element-visible-p bottom-gutter-visible-p 'str t) -(set-gutter-element-visible-p bottom-gutter-visible-p 'str2 t) +(set-gutter-element left-gutter 'str2 str2) +(set-gutter-element-visible-p left-gutter-visible-p 'str2 t)