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
}
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);
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))
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)
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
{
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);
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))
*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)
{
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
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;
}
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]);
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) =
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))
{
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 (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)
{
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 ");
#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,
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_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;
+}
+
\f
/*****************************************************************************
* 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
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
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)
{
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;
}
}
== 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
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;
}
\f
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");
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)
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);
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);
}
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);
}
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);
}
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);
}
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);
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);
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
image_instantiator_tab_control();
image_instantiator_labels();
image_instantiator_layout();
+ image_instantiator_native_layout();
}
void