[gtk+/composite-templates: 14/18] Removed gtk_container_get_composite_child() Get a reference to every internal object declared with g
- From: Juan Pablo Ugarte <jpu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/composite-templates: 14/18] Removed gtk_container_get_composite_child() Get a reference to every internal object declared with g
- Date: Tue, 31 Jul 2012 12:14:43 +0000 (UTC)
commit 961ee2ecdd840935e96ba73ebfaefbac093116f2
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date: Sun Jul 15 17:38:07 2012 -0300
Removed gtk_container_get_composite_child()
Get a reference to every internal object declared with gtk_container_class_declare_internal_child() which gets dropped on GtkContainer::destroy signal
Implemented "template" tag, this allow us to also build anarchist objects
gtk/gtkbuilder.c | 10 +--
gtk/gtkbuilder.h | 4 +-
gtk/gtkbuilderparser.c | 147 ++++++++++++++++++++++++++++++++++-----
gtk/gtkbuilderprivate.h | 2 +-
gtk/gtkcontainer.c | 146 ++++++++++++++++----------------------
gtk/gtkcontainer.h | 3 -
gtk/gtkdialog.tmpl.glade | 30 ++++----
gtk/gtkmessagedialog.tmpl.glade | 142 +++++++++++++++++++------------------
8 files changed, 287 insertions(+), 197 deletions(-)
---
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index c59b624..aaf9419 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -588,10 +588,7 @@ gtk_builder_get_internal_child (GtkBuilder *builder,
obj = gtk_buildable_get_internal_child (GTK_BUILDABLE (info->object),
builder,
childname);
- if (!obj && GTK_IS_CONTAINER (info->object))
- obj = (GObject *)gtk_container_get_composite_child (GTK_CONTAINER (info->object), childname);
-
- };
+ }
if (!obj)
{
@@ -659,8 +656,9 @@ _gtk_builder_construct (GtkBuilder *builder,
¶meters,
&construct_parameters);
- if (info->object && info->external)
+ if (info->object)
{
+ /* template_object */
obj = g_object_ref (info->object);
}
else if (info->constructor)
@@ -1519,7 +1517,7 @@ gtk_builder_connect_signals_default (GtkBuilder *builder,
g_warning ("Could not find signal handler '%s'", handler_name);
return;
}
-g_message ("%s %s %s", __func__, signal_name, handler_name);
+
if (connect_object)
g_signal_connect_object (object, signal_name, func, connect_object, flags);
else
diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h
index b2e8db5..dc5ac67 100644
--- a/gtk/gtkbuilder.h
+++ b/gtk/gtkbuilder.h
@@ -59,6 +59,7 @@ typedef struct _GtkBuilderPrivate GtkBuilderPrivate;
* @GTK_BUILDER_ERROR_VERSION_MISMATCH: The input file requires a newer version
* of GTK+.
* @GTK_BUILDER_ERROR_DUPLICATE_ID: An object id occurred twice.
+ * @GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH: The Class template is designed for a different class.
*
* Error codes that identify various errors that can occur while using
* #GtkBuilder.
@@ -73,7 +74,8 @@ typedef enum
GTK_BUILDER_ERROR_MISSING_PROPERTY_VALUE,
GTK_BUILDER_ERROR_INVALID_VALUE,
GTK_BUILDER_ERROR_VERSION_MISMATCH,
- GTK_BUILDER_ERROR_DUPLICATE_ID
+ GTK_BUILDER_ERROR_DUPLICATE_ID,
+ GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH
} GtkBuilderError;
GQuark gtk_builder_error_quark (void);
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index 0bdd118..19c657f 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -65,6 +65,32 @@ state_pop (ParserData *data)
#define state_pop_info(data, st) ((st*)state_pop(data))
static void
+error_generic (GError **error,
+ GtkBuilderError code,
+ ParserData *data,
+ const gchar *tag,
+ const gchar *format,
+ ...)
+{
+ gint line_number, char_number;
+ gchar *message;
+ va_list args;
+
+ g_markup_parse_context_get_position (data->ctx,
+ &line_number,
+ &char_number);
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ g_set_error (error, GTK_BUILDER_ERROR, code, "%s:%d:%d <%s> %s",
+ data->filename, line_number, char_number, tag, message);
+
+ g_free (message);
+}
+
+static void
error_missing_attribute (ParserData *data,
const gchar *tag,
const gchar *attribute,
@@ -643,6 +669,85 @@ parse_signal (ParserData *data,
info->tag.name = element_name;
}
+static void
+parse_template (ParserData *data,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ GError **error)
+{
+ GObject *parent = data->template_object;
+ const gchar *parent_class = NULL;
+ const gchar *class_name = NULL;
+ GType parent_type, class_type;
+ ObjectInfo *object_info;
+ gint i;
+
+ if (parent == NULL)
+ {
+ error_invalid_tag (data, element_name, NULL, error);
+ return;
+ }
+
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (strcmp (names[i], "class") == 0)
+ class_name = values[i];
+ else if (strcmp (names[i], "parent") == 0)
+ parent_class = values[i];
+ else
+ {
+ error_invalid_attribute (data, element_name, names[i], error);
+ return;
+ }
+ }
+
+ if (!class_name)
+ {
+ error_missing_attribute (data, element_name, "class", error);
+ return;
+ }
+
+ if (!parent_class)
+ {
+ error_missing_attribute (data, element_name, "parent", error);
+ return;
+ }
+
+ if ((class_type = g_type_from_name (class_name)) == G_TYPE_INVALID)
+ {
+ error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
+ element_name, "invalid class type found '%s'", class_name);
+ return;
+ }
+
+ parent_type = G_OBJECT_TYPE (parent);
+
+ if (!g_type_is_a (parent_type, class_type))
+ {
+ error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
+ element_name, "this template is for a class type %s not for %s",
+ class_name, G_OBJECT_TYPE_NAME (parent));
+ return;
+ }
+
+ if (!g_type_is_a (class_type, g_type_from_name (parent_class)))
+ {
+ error_generic (error, GTK_BUILDER_ERROR_TEMPLATE_CLASS_MISMATCH, data,
+ element_name, "class %s should derive from parent %s",
+ class_name, parent_class);
+ return;
+ }
+
+ object_info = g_slice_new0 (ObjectInfo);
+ object_info->object = parent;
+ object_info->object_type = parent_type;
+ object_info->id = g_strdup (_gtk_builder_object_get_name (parent));
+ object_info->tag.name = "object";
+
+ state_push (data, object_info);
+}
+
/* Called by GtkBuilder */
void
_free_signal_info (SignalInfo *info,
@@ -800,7 +905,7 @@ parse_custom (GMarkupParseContext *context,
if (strcmp (parent_info->tag.name, "object") == 0)
{
ObjectInfo* object_info = (ObjectInfo*)parent_info;
- if (!object_info->object || (object_info->object && object_info->external))
+ if (!object_info->object)
{
object_info->properties = g_slist_reverse (object_info->properties);
object_info->object = _gtk_builder_construct (data->builder,
@@ -905,6 +1010,8 @@ start_element (GMarkupParseContext *context,
parse_interface (data, element_name, names, values, error);
else if (strcmp (element_name, "menu") == 0)
_gtk_builder_menu_start (data, element_name, names, values, error);
+ else if (strcmp (element_name, "template") == 0)
+ parse_template (data, element_name, names, values, error);
else if (strcmp (element_name, "placeholder") == 0)
{
/* placeholder has no special treatmeant, but it needs an
@@ -975,12 +1082,6 @@ end_element (GMarkupParseContext *context,
}
else if (strcmp (element_name, "interface") == 0)
{
- ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
-
- if (object_info->signals && object_info->external)
- _gtk_builder_add_signals (data->builder, object_info->signals);
-
- free_object_info (object_info);
}
else if (data->requested_objects && !data->inside_requested_object)
{
@@ -1073,6 +1174,25 @@ end_element (GMarkupParseContext *context,
else if (strcmp (element_name, "placeholder") == 0)
{
}
+ else if (strcmp (element_name, "template") == 0)
+ {
+ if (data->template_object)
+ {
+ ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
+
+ object_info->properties = g_slist_reverse (object_info->properties);
+
+ /* This is just to apply properties to the external object */
+ _gtk_builder_construct (data->builder, object_info, error);
+
+ if (object_info->signals)
+ _gtk_builder_add_signals (data->builder, object_info->signals);
+
+ free_object_info (object_info);
+
+ data->template_object = NULL;
+ }
+ }
else
{
g_assert_not_reached ();
@@ -1172,17 +1292,8 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
if (parent)
{
- ObjectInfo *object_info = g_slice_new0 (ObjectInfo);
-
- object_info->object = parent;
- object_info->object_type = G_OBJECT_TYPE (parent);
- object_info->id = g_strdup (_gtk_builder_object_get_name (parent));
- object_info->external = TRUE;
-
- GTK_NOTE (BUILDER, g_print ("parsing with contextual parent info ptr %p %s\n", object_info, g_type_name (object_info->object_type)));
-
- state_push (data, object_info);
- object_info->tag.name = "object";
+ GTK_NOTE (BUILDER, g_print ("parsing with contextual parent %s ptr %p\n", G_OBJECT_TYPE_NAME (parent), parent));
+ data->template_object = parent;
}
data->requested_objects = NULL;
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index fb61514..bcac8bc 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -38,7 +38,6 @@ typedef struct {
GSList *signals;
GObject *object;
CommonInfo *parent;
- gboolean external;
} ObjectInfo;
typedef struct {
@@ -110,6 +109,7 @@ typedef struct {
gint cur_object_level;
GHashTable *object_ids;
+ GObject *template_object;
} ParserData;
typedef GType (*GTypeGetFunc) (void);
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 5a7d405..7ef0f83 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -241,7 +241,7 @@ typedef struct
typedef struct
{
gchar *name;
- GtkWidget *object;
+ GObject *object;
} InternalChild;
struct _GtkContainerClassPrivate
@@ -569,11 +569,22 @@ gtk_container_buildable_get_internal_child (GtkBuildable *buildable,
GtkBuilder *builder,
const gchar *childname)
{
- GtkWidget *child;
+ GArray *internal_children;
- child = gtk_container_get_composite_child (GTK_CONTAINER (buildable), childname);
- if (child) return G_OBJECT (child);
+ g_return_val_if_fail (childname && childname[0], NULL);
+ if ((internal_children = GTK_CONTAINER (buildable)->priv->internal_children))
+ {
+ gint i, len;
+
+ for (i = 0, len = internal_children->len; i < len; i++)
+ {
+ InternalChild *data = &g_array_index (internal_children, InternalChild, i);
+
+ if (g_strcmp0 (data->name, childname) == 0) return data->object;
+ }
+ }
+
return parent_buildable_iface->get_internal_child (buildable,
builder,
childname);
@@ -1380,39 +1391,6 @@ gtk_container_class_list_child_properties (GObjectClass *cclass,
}
/**
- * gtk_container_get_composite_child:
- * @container: a #GtkContainer
- * @composite_name: the name of a composite child as defined in the XML template
- *
- * Retrieves a composite child by name by checking composite children created from the template
- *
- * Returns: (transfer none): the composite child of @container with the name @composite_name
- */
-GtkWidget *
-gtk_container_get_composite_child (GtkContainer *container,
- const gchar *composite_name)
-{
- GArray *internal_children;
- gint i;
-
- g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
- g_return_val_if_fail (composite_name && composite_name[0], NULL);
-
- internal_children = container->priv->internal_children;
-
- if (!internal_children) return NULL;
-
- for (i = 0; i < internal_children->len; i++)
- {
- InternalChild *data = &g_array_index (internal_children, InternalChild, i);
-
- if (g_strcmp0 (data->name, composite_name) == 0) return data->object;
- }
-
- return NULL;
-}
-
-/**
* gtk_container_class_set_template:
* @container_class: a #GtkContainerClass
* @tmpl: the #GtkBuilder xml fragment used to build children
@@ -1575,45 +1553,52 @@ gtk_container_destroy (GtkWidget *widget)
gtk_container_unset_focus_chain (container);
if (priv->internal_children)
- g_array_unref (priv->internal_children);
-
- gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL);
-
- GTK_WIDGET_CLASS (parent_class)->destroy (widget);
-}
-
-static gboolean
-gtk_container_child_is_internal (GtkContainer *container, GtkWidget *child)
-{
- GArray *internal_children = container->priv->internal_children;
- gint i;
-
- if (!internal_children) return FALSE;
-
- for (i = 0; i < internal_children->len; i++)
{
- InternalChild *data = &g_array_index (internal_children, InternalChild, i);
+ GArray *internal_children = priv->internal_children;
+ gint i, len = internal_children->len;
- if (data->object == child) return TRUE;
+ for (i = 0; i < len; i++)
+ {
+ InternalChild *data = &g_array_index (internal_children, InternalChild, i);
+ g_object_unref (data->object);
+ }
+ g_array_unref (internal_children);
+ priv->internal_children = NULL;
}
- return FALSE;
+ gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL);
+
+ GTK_WIDGET_CLASS (parent_class)->destroy (widget);
}
static void
-gtk_container_child_set_internal (GtkContainer *container, GtkWidget *child, gchar *name)
+gtk_container_child_set_internal (GtkContainer *container,
+ InternalChildData *child,
+ GObject *internal)
{
GtkContainerPrivate *priv = container->priv;
InternalChild data;
+ GObject **retval;
if (!priv->internal_children)
priv->internal_children = g_array_new (FALSE, FALSE, sizeof (InternalChild));
-
- gtk_widget_set_composite_name (child, name);
- data.name = name;
- data.object = child;
+ if (GTK_IS_WIDGET (internal))
+ gtk_widget_set_composite_name (GTK_WIDGET (internal), child->name);
+
+ data.name = child->name;
+ data.object = g_object_ref (internal);
g_array_append_val (priv->internal_children, data);
+
+ if (child->private)
+ {
+ gpointer pstruct = G_TYPE_INSTANCE_GET_PRIVATE (container, child->type, gpointer);
+ retval = G_STRUCT_MEMBER_P (pstruct, child->offset);
+ }
+ else
+ retval = G_STRUCT_MEMBER_P (container, child->offset);
+
+ *retval = internal;
}
static GObject *
@@ -1662,38 +1647,31 @@ gtk_container_constructor (GType type,
if (ret)
{
- if (cpriv->connect_func)
- gtk_builder_connect_signals_full (builder, cpriv->connect_func, container);
- else
- gtk_builder_connect_signals (builder, container);
-
/* Setup internal children */
for (children = cpriv->internal_children; children; children = g_list_next (children))
{
InternalChildData *child = children->data;
- GtkContainer *parent;
- GtkWidget *widget;
- gpointer structure;
- GObject **retval;
- gchar *name;
-
- name = child->name;
- structure = (child->private) ? G_TYPE_INSTANCE_GET_PRIVATE (object, child->type, gpointer) : (gpointer) object;
- retval = G_STRUCT_MEMBER_P (structure, child->offset);
- *retval = gtk_builder_get_object (builder, name);
- widget = GTK_WIDGET (*retval);
-
- parent = GTK_CONTAINER (gtk_widget_get_parent (widget));
- if (container != parent && gtk_container_child_is_internal (parent, widget))
- gtk_container_child_set_internal (parent, widget, name);
-
- gtk_container_child_set_internal (container, widget, name);
+ GObject *internal;
+
+ if ((internal = gtk_builder_get_object (builder, child->name)))
+ gtk_container_child_set_internal (container, child, internal);
+ else
+ {
+ g_warning ("Unable to setup internal child %s while building GtkContainer class %s",
+ g_type_name (type), child->name);
+ continue;
+ }
}
+
+ if (cpriv->connect_func)
+ gtk_builder_connect_signals_full (builder, cpriv->connect_func, container);
+ else
+ gtk_builder_connect_signals (builder, container);
}
else
{
g_critical ("Unable to build GtkContainer class %s from template: %s",
- G_OBJECT_TYPE_NAME (container), error->message);
+ g_type_name (type), error->message);
g_error_free (error);
}
diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h
index 6790e3f..5ef3828 100644
--- a/gtk/gtkcontainer.h
+++ b/gtk/gtkcontainer.h
@@ -228,9 +228,6 @@ void gtk_container_forall (GtkContainer *container,
void gtk_container_class_handle_border_width (GtkContainerClass *klass);
-GtkWidget *gtk_container_get_composite_child (GtkContainer *container,
- const gchar *composite_name);
-
/* Class-level functions */
void gtk_container_class_set_template (GtkContainerClass *container_class,
const gchar *tmpl,
diff --git a/gtk/gtkdialog.tmpl.glade b/gtk/gtkdialog.tmpl.glade
index 6c69d2e..6fe9195 100644
--- a/gtk/gtkdialog.tmpl.glade
+++ b/gtk/gtkdialog.tmpl.glade
@@ -1,22 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.20"/>
- <child>
- <object class="GtkBox" id="vbox">
- <property name="visible">True</property>
- <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <template class="GtkDialog" parent="GtkWindow">
<child>
- <object class="GtkButtonBox" id="action_area">
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <object class="GtkBox" id="vbox">
<property name="visible">True</property>
- <property name="layout_style">end</property>
+ <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
+ <child>
+ <object class="GtkButtonBox" id="action_area">
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
</child>
- </object>
- </child>
+ </template>
</interface>
diff --git a/gtk/gtkmessagedialog.tmpl.glade b/gtk/gtkmessagedialog.tmpl.glade
index 8213c9b..b499186 100644
--- a/gtk/gtkmessagedialog.tmpl.glade
+++ b/gtk/gtkmessagedialog.tmpl.glade
@@ -1,74 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.20"/>
- <child internal-child="vbox">
- <object class="GtkBox" id="vbox">
- <property name="spacing">14</property>
- <child>
- <object class="GtkBox" id="hbox1">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="spacing">12</property>
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
- <child>
- <object class="GtkImage" id="image">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="icon-size">6</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="vbox1">
- <property name="visible">True</property>
- <property name="spacing">12</property>
- <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
- <child>
- <object class="GtkLabel" id="label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="label" translatable="yes">primary message</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="secondary_label">
- <property name="visible">False</property>
- <property name="no_show_all">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="label" translatable="yes">secondary message</property>
- <property name="wrap">True</property>
- <property name="selectable">True</property>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="action_area">
- <property name="border_width">5</property>
- <property name="spacing">6</property>
- </object>
- </child>
- </object>
- </child>
+ <template class="GtkMessageDialog" parent="GtkDialog">
+ <child internal-child="vbox">
+ <object class="GtkBox" id="vbox">
+ <property name="spacing">14</property>
+ <child>
+ <object class="GtkBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">12</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="yalign">0</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">primary message</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="secondary_label">
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">secondary message</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="action_area">
+ <property name="border_width">5</property>
+ <property name="spacing">6</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]