+/* 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 (IMAGE_INSTANCE_TYPE (ii) != IMAGE_WIDGET)
+ 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 (XDEVICE (ii->device), update_widget, (ii));
+
+ /* Device-format specific methods */
+ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
+ 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
+widget_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);
+ 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);
+ if (height) *height = IMAGE_INSTANCE_HEIGHT (ii);
+
+ if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
+ ||
+ IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
+ {
+ /* .. then try device specific methods ... */
+ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
+ IMAGE_INSTANCE_WIDGET_TYPE (ii),
+ ERROR_ME_NOT);
+ if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
+ IIFORMAT_METH (meths, query_geometry, (image_instance,
+ width, height, disp,
+ 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, query_geometry))
+ IIFORMAT_METH (meths, query_geometry, (image_instance,
+ width, height, disp,
+ domain));
+ else
+ {
+ unsigned int w, h;
+
+ /* Then if we are allowed to resize the widget, make the
+ size the same as the text dimensions. */
+ 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 (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
+ *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
+widget_layout (Lisp_Object image_instance,
+ unsigned int width, unsigned int height, Lisp_Object domain)
+{
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ struct image_instantiator_methods* meths;
+
+ /* .. then try device specific methods ... */
+ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
+ 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));
+ 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));
+ }
+}
+