}
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);
if (EQ (prop, Q_text))
{
IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
+ IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
}
/* Now try device specific methods first ... */
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 (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));
+}
+
/* Query for a widgets desired geometry. If no type specific method is
provided then use the widget text to calculate sizes. */
static void
{
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);
*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);
+ }
}
}
IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
+ 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;
/* 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);
+ Lisp_Object gii = glyph_image_instance (border, domain, ERROR_ME, 1);
+ /* 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);
}
else
{
/* make sure the image is instantiated */
Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
+ /* 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. */
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))
{
if (!NILP (pixheight))
{
- ph = XINT (pixheight);
- IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
+ if (!INTP (pixwidth))
+ 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)
{
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;
#ifdef DEBUG_WIDGETS
debug_widget_instances++;
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;
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);
}
}
}
+/* 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_percent))
+ {
+ CHECK_INT (val);
+ IMAGE_INSTANCE_WIDGET_PROPS (ii)
+ = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
+ IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii) = 1;
+
+ return Qt;
+ }
+ return Qunbound;
+}
+
\f
/*****************************************************************************
* widget layout *
}
else
{
-
nitems ++;
if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
== LAYOUT_HORIZONTAL)
/* Now layout subwidgets if they require it. */
image_instance_layout (glyph, gwidth, gheight, domain);
}
-
- IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = width;
- IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = height;
}
\f
#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)
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);
}
IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
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);
}
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_METHOD (progress_gauge, set_property);
VALID_WIDGET_KEYWORDS (progress_gauge);
VALID_GUI_KEYWORDS (progress_gauge);
}
IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
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);
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_pixel_width, check_valid_int_or_function);
+ IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int_or_function);
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);