X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fglyphs-widget.c;h=d7c8c587a4b7f4190ada214499a18d76dd71c1b4;hb=3aca7317dd930beecbddba646284279744087e69;hp=b5881ca1a4b86b15612cb66304a7d58b3831afff;hpb=716cfba952c1dc0d2cf5c968971f3780ba728a89;p=chise%2Fxemacs-chise.git- diff --git a/src/glyphs-widget.c b/src/glyphs-widget.c index b5881ca..d7c8c58 100644 --- a/src/glyphs-widget.c +++ b/src/glyphs-widget.c @@ -55,9 +55,12 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control); Lisp_Object Qtab_control; DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout); Lisp_Object Qlayout; +DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout); +Lisp_Object Qnative_layout; Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items; -Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border; +Lisp_Object Q_image, Q_text, Q_orientation, Q_justify, Q_border; +Lisp_Object Q_margin_width; Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; #ifdef DEBUG_WIDGETS @@ -149,6 +152,13 @@ check_valid_callback (Lisp_Object data) } static void +check_valid_int_or_function (Lisp_Object data) +{ + if (!INTP (data) && !CONSP (data)) + signal_simple_error ("must be an integer or expresssion", data); +} + +static void check_valid_symbol (Lisp_Object data) { CHECK_SYMBOL (data); @@ -265,7 +275,7 @@ widget_property (Lisp_Object image_instance, Lisp_Object prop) return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil); /* .. then try device specific methods ... */ - meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + meths = decode_device_ii_format (image_instance_device (image_instance), IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); if (meths && HAS_IIFORMAT_METH_P (meths, property)) @@ -291,10 +301,11 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v if (EQ (prop, Q_text)) { IMAGE_INSTANCE_WIDGET_TEXT (ii) = val; + IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1; } /* Now try device specific methods first ... */ - meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + meths = decode_device_ii_format (image_instance_device (image_instance), IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); if (meths && HAS_IIFORMAT_METH_P (meths, set_property) @@ -320,6 +331,46 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v return val; } +/* Like the rest of redisplay, we want widget updates to occur + asynchronously. Thus toolkit specific methods for setting + properties must be called by redisplay instead of by + *_set_property. Thus *_set_property records the change and this + function actually implements it. We want to be slightly clever + about this however by supplying format specific functions for the + updates instead of lumping them all into this function. Note that + there is no need for format generic functions. */ +void +update_widget (Lisp_Object widget) +{ + Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget); + struct image_instantiator_methods* meths; + + if (!WIDGET_IMAGE_INSTANCEP (widget) + || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout) + || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout)) + return; + + /* Device generic methods. We must update the widget's size as it + may have been changed by the the layout routines. We also do this + here so that explicit resizing from lisp does not result in + synchronous updates. */ + MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), update_widget, (ii)); + + /* Device-format specific methods */ + meths = decode_device_ii_format (image_instance_device (widget), + IMAGE_INSTANCE_WIDGET_TYPE (ii), + ERROR_ME_NOT); + MAYBE_IIFORMAT_METH (meths, update, (widget)); + + /* Pick up the items we recorded earlier. */ + if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)) + { + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii); + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; + } +} + /* Query for a widgets desired geometry. If no type specific method is provided then use the widget text to calculate sizes. */ static void @@ -329,6 +380,8 @@ widget_query_geometry (Lisp_Object image_instance, { Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); struct image_instantiator_methods* meths; + Lisp_Object dynamic_width = Qnil; + Lisp_Object dynamic_height = Qnil; /* First just set up what we already have. */ if (width) *width = IMAGE_INSTANCE_WIDTH (ii); @@ -339,7 +392,7 @@ widget_query_geometry (Lisp_Object image_instance, IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) { /* .. then try device specific methods ... */ - meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + meths = decode_device_ii_format (image_instance_device (image_instance), IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) @@ -371,10 +424,23 @@ widget_query_geometry (Lisp_Object image_instance, *height = h + 2 * WIDGET_BORDER_HEIGHT; } } + /* Finish off with dynamic sizing. */ + if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii))) + { + dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)); + if (INTP (dynamic_width)) + *width = XINT (dynamic_width); + } + if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) + { + dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)); + if (INTP (dynamic_height)) + *height = XINT (dynamic_height); + } } } -static void +static int widget_layout (Lisp_Object image_instance, unsigned int width, unsigned int height, Lisp_Object domain) { @@ -382,21 +448,22 @@ widget_layout (Lisp_Object image_instance, struct image_instantiator_methods* meths; /* .. then try device specific methods ... */ - meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), + meths = decode_device_ii_format (image_instance_device (image_instance), IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); if (meths && HAS_IIFORMAT_METH_P (meths, layout)) - IIFORMAT_METH (meths, layout, (image_instance, - width, height, domain)); + return IIFORMAT_METH (meths, layout, (image_instance, + width, height, domain)); else { /* ... then format specific methods ... */ meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), ERROR_ME_NOT); if (meths && HAS_IIFORMAT_METH_P (meths, layout)) - IIFORMAT_METH (meths, layout, (image_instance, - width, height, domain)); + return IIFORMAT_METH (meths, layout, (image_instance, + width, height, domain)); } + return 1; } static void @@ -453,9 +520,13 @@ initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type) IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil); IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); + IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil; + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; + IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil; + IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil; IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1; IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1; - IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL; IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0; } @@ -481,15 +552,15 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties); Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); + Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width); int pw=0, ph=0, tw=0, th=0; /* this just does pixel type sizing */ subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, dest_mask, domain); - - if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK))) - incompatible_image_types (instantiator, dest_mask, - IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK); + + if (!(dest_mask & IMAGE_WIDGET_MASK)) + incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK); initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]); @@ -500,53 +571,10 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, if (!NILP (face)) SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face)); - /* Do layout specific initialisation. This feels a bit tacky, but - the alternative is a myriad of different little functions. */ - if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)) - { - Lisp_Object rest, children = Qnil; - Lisp_Object border = find_keyword_in_vector (instantiator, Q_border); - - if (NILP (orient)) - { - IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL; - } - IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT; - - if (EQ (border, Qt)) - { - IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in; - } - else if (GLYPHP (border)) - { - /* We are going to be sneaky here and add the border text as - just another child, the layout and output routines don't know - this and will just display at the offsets we prescribe. */ - children = Fcons (glyph_image_instance (border, domain, ERROR_ME, 1), - children); - IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0); - } - else - { - IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border; - } - - /* Pick up the sub-widgets. */ - LIST_LOOP (rest, items) - { - /* make sure the image is instantiated */ - Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1); - children = Fcons (gii, children); - /* Make sure elements in the layout are in the order the - user expected. */ - children = Fnreverse (children); - } - IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children; - } /* retrieve the gui item information. This is easy if we have been provided with a vector, more difficult if we have just been given keywords */ - else if (STRINGP (desc) || NILP (desc)) + if (STRINGP (desc) || NILP (desc)) { /* big cheat - we rely on the fact that a gui item looks like an instantiator */ IMAGE_INSTANCE_WIDGET_ITEMS (ii) = @@ -556,14 +584,16 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, else IMAGE_INSTANCE_WIDGET_ITEMS (ii) = gui_parse_item_keywords_no_errors (desc); - + /* Pick up the orientation before we do our first layout. */ if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical)) - IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1; + IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL; /* parse more gui items out of the properties */ if (!NILP (props) - && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)) + && + !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout) + && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout)) { if (NILP (items)) { @@ -583,8 +613,13 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, geometry gets called. */ if (!NILP (pixwidth)) /* pixwidth takes precendent */ { - pw = XINT (pixwidth); - IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; + if (!INTP (pixwidth)) + IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth; + else + { + pw = XINT (pixwidth); + IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; + } } else if (!NILP (width)) { @@ -594,8 +629,13 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, if (!NILP (pixheight)) { - ph = XINT (pixheight); - IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; + if (!INTP (pixheight)) + IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight; + else + { + ph = XINT (pixheight); + IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; + } } else if (!NILP (height) && XINT (height) > 1) { @@ -629,17 +669,23 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; } - /* When we create the widgets the window system expects a valid - size, so If we still don' t have sizes, call layout to pick them - up. If query_geometry or layout relies on the widget being in - existence then we are in catch 22. */ - image_instance_layout (image_instance, - pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY, - ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY, - domain); - /* Layout has already been done so we don't need to re-layout. */ - IMAGE_INSTANCE_DIRTYP (ii) = 0; + /* Pick up the margin width. */ + if (!NILP (mwidth)) + IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth); + + /* Layout for the layout widget is premature at this point since the + children will not have been instantiated. We can't instantiate + them until the device instantiation method for the layout has + been executed. We do however want to record any specified + dimensions. */ + if (pw) IMAGE_INSTANCE_WIDTH (ii) = pw; + if (ph) IMAGE_INSTANCE_HEIGHT (ii) = ph; +} +static void +widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object domain) +{ #ifdef DEBUG_WIDGETS debug_widget_instances++; stderr_out ("instantiated "); @@ -648,6 +694,33 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, #endif } +/* Get the geometry of a button control. We need to adjust the size + depending on the type of button. */ +static void +button_query_geometry (Lisp_Object image_instance, + unsigned int* width, unsigned int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + unsigned 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 + 2 * WIDGET_BORDER_WIDTH; + + if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio) + || + EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle)) + /* This is an approximation to the size of the actual button bit. */ + *width += 12; + } + if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)) + *height = h + 2 * WIDGET_BORDER_HEIGHT; +} + /* tree-view geometry - get the height right */ static void tree_view_query_geometry (Lisp_Object image_instance, @@ -682,7 +755,7 @@ tab_control_query_geometry (Lisp_Object image_instance, enum image_instance_geometry disp, Lisp_Object domain) { Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii); + Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); Lisp_Object rest; unsigned int tw = 0, th = 0; @@ -693,7 +766,7 @@ tab_control_query_geometry (Lisp_Object image_instance, query_string_geometry (XGUI_ITEM (XCAR (rest))->name, IMAGE_INSTANCE_WIDGET_FACE (ii), &w, &h, 0, domain); - tw += 2 * WIDGET_BORDER_WIDTH; /* some bias */ + tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */ tw += w; th = max (th, h + 2 * WIDGET_BORDER_HEIGHT); } @@ -711,16 +784,68 @@ tab_control_query_geometry (Lisp_Object image_instance, } } +/* Get the geometry of a tab control. This is based on the number of + items and text therin in the tab control. */ +static Lisp_Object +tab_control_set_property (Lisp_Object image_instance, + Lisp_Object prop, + Lisp_Object val) +{ + /* Record new items for update. *_tab_control_update will do the + rest. */ + if (EQ (prop, Q_items)) + { + Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + + check_valid_item_list_1 (val); + + /* Don't set the actual items since we might decide not to use + the new ones (because nothing has really changed). If we did + set them and didn't use them then we would get into whole + heaps of trouble when the old items get GC'd. */ + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = + Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + parse_gui_item_tree_children (val)); + IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1; + + return Qt; + } + return Qunbound; +} + +/* set the properties of a progres guage */ +static Lisp_Object +progress_gauge_set_property (Lisp_Object image_instance, + Lisp_Object prop, + Lisp_Object val) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_value)) + { + CHECK_INT (val); +#ifdef DEBUG_WIDGET_OUTPUT + printf ("progress gauge value set to %ld\n", XINT (val)); +#endif + IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = + copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); +#ifdef ERROR_CHECK_GLYPHS + assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))); +#endif + if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) + XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = val; + + IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1; + + return Qt; + } + return Qunbound; +} + /***************************************************************************** * widget layout * *****************************************************************************/ -static int -layout_possible_dest_types (void) -{ - return IMAGE_LAYOUT_MASK; -} - /* we need to convert things like glyphs to images, eval expressions etc.*/ static Lisp_Object @@ -748,6 +873,79 @@ layout_normalize (Lisp_Object inst, Lisp_Object console_type) return inst; } +static void +layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); + Lisp_Object border = find_keyword_in_vector (instantiator, Q_border); + + /* Do widget type instantiation first. */ + widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, + dest_mask, domain); + + if (NILP (orient)) + { + IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL; + } + + if (EQ (border, Qt)) + { + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in; + } + else + { + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border; + } + /* We don't do the children yet as we might not have a containing + window. */ +} + +static void +layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object domain) +{ + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); + Lisp_Object rest, children = Qnil; + + if (GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) + { + /* We are going to be sneaky here and add the border text as + just another child, the layout and output routines don't know + this and will just display at the offsets we prescribe. */ + Lisp_Object gii = glyph_image_instance + (IMAGE_INSTANCE_LAYOUT_BORDER (ii), + image_instance, ERROR_ME, 1); + + if (!IMAGE_INSTANCEP (gii)) + return; + /* make sure we are designated as the parent. */ + XIMAGE_INSTANCE_PARENT (gii) = image_instance; + children = Fcons (gii, children); + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0); + } + + /* Pick up the sub-widgets. */ + LIST_LOOP (rest, items) + { + /* make sure the image is instantiated */ + Lisp_Object gii = glyph_image_instance (XCAR (rest), + image_instance, ERROR_ME, 1); + if (!IMAGE_INSTANCEP (gii)) + return; + /* make sure we are designated as the parent. */ + XIMAGE_INSTANCE_PARENT (gii) = image_instance; + children = Fcons (gii, children); + } + /* Make sure elements in the layout are in the order the + user expected. */ + children = Fnreverse (children); + IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children; +} + /* Layout widget. Sizing commentary: we have a number of problems that we would like to address. Some consider some of these more important than others. It used to be that size information was @@ -804,57 +1002,85 @@ layout_query_geometry (Lisp_Object image_instance, unsigned int* width, 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; + unsigned int gheight, gwidth; + + /* If we are not initialized then we won't have any children. */ + if (!IMAGE_INSTANCE_INITIALIZED (ii)) + return; + /* First just set up what we already have. */ + if (width) *width = IMAGE_INSTANCE_WIDTH (ii); + if (height) *height = IMAGE_INSTANCE_HEIGHT (ii); + + /* If we are not allowed to dynamically size then return. */ + if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) + && + !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii)) + return; + + /* Pick up the border text if we have one. */ + if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) + { + image_instance_query_geometry (XCAR (items), &gwidth, &gheight, disp, domain); + ph_adjust = gheight / 2; + items = XCDR (items); + } + /* Flip through the items to work out how much stuff we have to display */ LIST_LOOP (rest, items) { Lisp_Object glyph = XCAR (rest); - unsigned int gheight, gwidth; - image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain); - /* Pick up the border text if we have one. */ - if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) - && NILP (XCDR (rest))) + nitems ++; + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) + == LAYOUT_HORIZONTAL) { - ph_adjust = gheight / 2; + maxph = max (maxph, gheight); + maxpw += gwidth; } else { - - nitems ++; - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - { - maxph = max (maxph, gheight); - maxpw += gwidth; - } - else - { - maxpw = max (maxpw, gwidth); - maxph += gheight; - } + maxpw = max (maxpw, gwidth); + maxph += gheight; } } - /* work out spacing between items and bounds of the layout. No user - provided width so we just do default spacing. */ - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2; + /* Work out minimum space we need to fit all the items. This could + have been fixed by the user. */ + if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii))) + { + Lisp_Object dynamic_width = + Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)); + 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 - *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2; + *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)); /* Work out vertical spacings. */ - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_VERTICAL) - *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust; - else - *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust; + if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii))) + { + Lisp_Object dynamic_height = + Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)); + 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 + *height = maxph + (2 * WIDGET_BORDER_HEIGHT + + IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust; } - -static void +int layout_layout (Lisp_Object image_instance, unsigned int width, unsigned int height, Lisp_Object domain) { @@ -865,38 +1091,44 @@ layout_layout (Lisp_Object image_instance, horiz_spacing, vert_spacing, ph_adjust = 0; unsigned int gheight, gwidth; - /* flip through the items to work out how much stuff we have to display */ + /* 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. */ + if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))) + { + Lisp_Object border = XCAR (items); + items = XCDR (items); + image_instance_query_geometry (border, &gwidth, &gheight, + IMAGE_DESIRED_GEOMETRY, domain); + /* #### Really, what should this be? */ + XIMAGE_INSTANCE_XOFFSET (border) = 10; + XIMAGE_INSTANCE_YOFFSET (border) = 0; + ph_adjust = gheight / 2; + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); + + image_instance_layout (border, gwidth, gheight, domain); + } + + /* Flip through the items to work out how much stuff we have to display. */ LIST_LOOP (rest, items) { Lisp_Object glyph = XCAR (rest); image_instance_query_geometry (glyph, &gwidth, &gheight, IMAGE_DESIRED_GEOMETRY, domain); - - /* Pick up the border text if we have one. */ - if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) - && NILP (XCDR (rest))) + nitems ++; + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) + == LAYOUT_HORIZONTAL) { - XIMAGE_INSTANCE_XOFFSET (glyph) = 10; /* Really, what should this be? */ - XIMAGE_INSTANCE_YOFFSET (glyph) = 0; - ph_adjust = gheight / 2; - IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); + maxph = max (maxph, gheight); + maxpw += gwidth; } else { - - nitems ++; - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - { - maxph = max (maxph, gheight); - maxpw += gwidth; - } - else - { - maxpw = max (maxpw, gwidth); - maxph += gheight; - } + maxpw = max (maxpw, gwidth); + maxph += gheight; } } @@ -910,20 +1142,26 @@ layout_layout (Lisp_Object image_instance, == LAYOUT_HORIZONTAL) /* We have a larger area to display in so distribute the space evenly. */ - horiz_spacing = (width - maxpw) / (nitems + 1); + horiz_spacing = (width - (maxpw + + IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) + / (nitems + 1); else - horiz_spacing = (width - maxpw) / 2; + horiz_spacing = (width - maxpw) / 2 + - IMAGE_INSTANCE_MARGIN_WIDTH (ii); if (height < maxph) vert_spacing = WIDGET_BORDER_HEIGHT * 2; else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) == LAYOUT_VERTICAL) - vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1); + vert_spacing = (height - (maxph + ph_adjust + + IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2)) + / (nitems + 1); else - vert_spacing = (height - (maxph + ph_adjust)) / 2; + vert_spacing = (height - (maxph + ph_adjust)) / 2 + - IMAGE_INSTANCE_MARGIN_WIDTH (ii); - y = vert_spacing + ph_adjust; - x = horiz_spacing; + y = 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 attention to justification. Make sure we don't mess with the @@ -935,49 +1173,77 @@ layout_layout (Lisp_Object image_instance, image_instance_query_geometry (glyph, &gwidth, &gheight, IMAGE_DESIRED_GEOMETRY, domain); - if (!INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) - || !NILP (XCDR (rest))) - { - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - { - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_RIGHT) - y = height - (gheight + vert_spacing); - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_CENTER) - y = (height - gheight) / 2; - } - else - { - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_RIGHT) - x = width - (gwidth + horiz_spacing); - if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) - == LAYOUT_JUSTIFY_CENTER) - x = (width - gwidth) / 2; - } + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) + == LAYOUT_HORIZONTAL) + { + if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) + == LAYOUT_JUSTIFY_RIGHT) + y = height - (gheight + vert_spacing); + if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) + == LAYOUT_JUSTIFY_CENTER) + y = (height - gheight) / 2; + } + else + { + if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) + == LAYOUT_JUSTIFY_RIGHT) + x = width - (gwidth + horiz_spacing); + if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) + == LAYOUT_JUSTIFY_CENTER) + x = (width - gwidth) / 2; + } - XIMAGE_INSTANCE_XOFFSET (glyph) = x; - XIMAGE_INSTANCE_YOFFSET (glyph) = y; + XIMAGE_INSTANCE_XOFFSET (glyph) = x; + XIMAGE_INSTANCE_YOFFSET (glyph) = y; - if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) - == LAYOUT_HORIZONTAL) - { - x += (gwidth + horiz_spacing); - } - else - { - y += (gheight + vert_spacing); - } - } + if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) + == LAYOUT_HORIZONTAL) + { + x += (gwidth + horiz_spacing); + } + else + { + y += (gheight + vert_spacing); + } /* Now layout subwidgets if they require it. */ image_instance_layout (glyph, gwidth, gheight, domain); } + return 1; +} - IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = width; - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = height; +/* Layout subwindows if they are real subwindows. */ +static int +native_layout_layout (Lisp_Object image_instance, + unsigned int width, unsigned int height, + Lisp_Object domain) +{ + Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object rest; + + /* The first time this gets called, the layout will be only + partially instantiated. The children get done in + post_instantiate. */ + if (!IMAGE_INSTANCE_INITIALIZED (ii)) + return 0; + + /* Defining this overrides the default layout_layout so we first have to call that to get + suitable instances and values set up. */ + layout_layout (image_instance, width, height, domain); + + LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)) + { + struct display_glyph_area dga; + dga.xoffset = 0; + dga.yoffset = 0; + dga.width = IMAGE_INSTANCE_WIDTH (ii); + dga.height = IMAGE_INSTANCE_HEIGHT (ii); + + map_subwindow (XCAR (rest), + IMAGE_INSTANCE_XOFFSET (ii), + IMAGE_INSTANCE_YOFFSET (ii), &dga); + } + return 1; } @@ -994,11 +1260,11 @@ syms_of_glyphs_widget (void) defkeyword (&Q_properties, ":properties"); defkeyword (&Q_items, ":items"); defkeyword (&Q_image, ":image"); - defkeyword (&Q_percent, ":percent"); defkeyword (&Q_text, ":text"); defkeyword (&Q_orientation, ":orientation"); defkeyword (&Q_justify, ":justify"); defkeyword (&Q_border, ":border"); + defkeyword (&Q_margin_width, ":margin-width"); defsymbol (&Qetched_in, "etched-in"); defsymbol (&Qetched_out, "etched-out"); @@ -1019,14 +1285,15 @@ syms_of_glyphs_widget (void) IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string); \ IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything); \ IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback); \ + IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \ IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector); \ } while (0) #define VALID_WIDGET_KEYWORDS(type) do { \ IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int); \ IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int); \ - IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int); \ - IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int); \ + IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function);\ + IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function);\ IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face); \ } while (0) @@ -1046,7 +1313,10 @@ static void image_instantiator_buttons (void) IIFORMAT_HAS_SHARED_METHOD (button, validate, widget); IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget); IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget); + IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow); + IIFORMAT_HAS_METHOD (button, query_geometry); IIFORMAT_VALID_KEYWORD (button, Q_image, check_valid_glyph_or_instantiator); VALID_WIDGET_KEYWORDS (button); @@ -1059,6 +1329,8 @@ static void image_instantiator_edit_fields (void) IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget); IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget); 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); VALID_WIDGET_KEYWORDS (edit_field); VALID_GUI_KEYWORDS (edit_field); } @@ -1068,11 +1340,13 @@ static void image_instantiator_combo_box (void) INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box"); IIFORMAT_HAS_METHOD (combo_box, validate); IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget); + IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow); + VALID_GUI_KEYWORDS (combo_box); IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int); IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int); - IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int); + IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int_or_function); IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face); IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list); } @@ -1083,10 +1357,12 @@ static void image_instantiator_scrollbar (void) IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget); IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow); VALID_GUI_KEYWORDS (scrollbar); - IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int); - IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int); + IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int_or_function); + IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int_or_function); IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face); } @@ -1096,6 +1372,9 @@ static void image_instantiator_progress_guage (void) IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow); + IIFORMAT_HAS_METHOD (progress_gauge, set_property); VALID_WIDGET_KEYWORDS (progress_gauge); VALID_GUI_KEYWORDS (progress_gauge); } @@ -1106,6 +1385,8 @@ static void image_instantiator_tree_view (void) IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow); IIFORMAT_HAS_METHOD (tree_view, query_geometry); VALID_WIDGET_KEYWORDS (tree_view); VALID_GUI_KEYWORDS (tree_view); @@ -1118,7 +1399,10 @@ static void image_instantiator_tab_control (void) IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box); IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow); IIFORMAT_HAS_METHOD (tab_control, query_geometry); + IIFORMAT_HAS_METHOD (tab_control, set_property); VALID_WIDGET_KEYWORDS (tab_control); VALID_GUI_KEYWORDS (tab_control); IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation); @@ -1130,25 +1414,50 @@ static void image_instantiator_labels (void) INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label"); IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow); VALID_WIDGET_KEYWORDS (label); IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); } +#define VALID_LAYOUT_KEYWORDS(layout) \ + 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_border, check_valid_border); \ + IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int); \ + IIFORMAT_VALID_KEYWORD (layout, Q_items, \ + check_valid_glyph_or_instantiator_list) + static void image_instantiator_layout (void) { INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout"); - IIFORMAT_HAS_METHOD (layout, possible_dest_types); - IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget); + IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget); + IIFORMAT_HAS_METHOD (layout, instantiate); + IIFORMAT_HAS_METHOD (layout, post_instantiate); + IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow); IIFORMAT_HAS_METHOD (layout, normalize); IIFORMAT_HAS_METHOD (layout, query_geometry); IIFORMAT_HAS_METHOD (layout, layout); - IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int); - IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int); - IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); - IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); - IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); - IIFORMAT_VALID_KEYWORD (layout, Q_items, - check_valid_glyph_or_instantiator_list); + + VALID_GUI_KEYWORDS (layout); + VALID_LAYOUT_KEYWORDS (layout); +} + +static void image_instantiator_native_layout (void) +{ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout"); + IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget); + IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout); + IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout); + IIFORMAT_HAS_METHOD (native_layout, layout); + IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow); + IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout); + IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout); + IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout); + + VALID_GUI_KEYWORDS (native_layout); + VALID_LAYOUT_KEYWORDS (native_layout); } void @@ -1164,6 +1473,7 @@ image_instantiator_format_create_glyphs_widget (void) image_instantiator_tab_control(); image_instantiator_labels(); image_instantiator_layout(); + image_instantiator_native_layout(); } void