Index: lib/objchange.h
===================================================================
--- lib/objchange.h	(revision 3732)
+++ lib/objchange.h	(working copy)
@@ -26,6 +26,14 @@
 typedef void (*ObjectChangeRevertFunc)(ObjectChange *change, DiaObject *obj);
 typedef void (*ObjectChangeFreeFunc)(ObjectChange *change);
 
+/*
+   RFC: Why do the functions require the changed object as an
+   argument? It doesn't make sense to have a "change" that is not
+   associated with a particular object. The object should be specified
+   by the change itself. Why would anyone try to apply an arbitrary
+   change to some arbitrary object other than the one involved in
+   originally making that change?
+ */
 struct _ObjectChange {
   /*! If apply == transaction_point_pointer then this is a transaction
      point. Otherwise this is applying the change */
Index: lib/group.c
===================================================================
--- lib/group.c	(revision 3732)
+++ lib/group.c	(working copy)
@@ -25,6 +25,7 @@
 #include "connectionpoint.h"
 #include "group.h"
 #include "properties.h"
+#include "propinternals.h"
 #include "diarenderer.h"
 
 struct _Group {
@@ -38,6 +39,20 @@
   PropDescription *pdesc;
 };
 
+typedef struct _GroupPropChange GroupPropChange;
+struct _GroupPropChange {
+  ObjectChange obj_change;
+  Group *group;
+  GList *changes_per_object;
+};
+
+static GroupPropChange* group_apply_props_from_dialog(Group *group
+                                                  , WIDGET *dialog_widget);
+static GroupPropChange* group_apply_props(Group *group, GPtrArray *props);
+static void group_prop_change_apply(GroupPropChange *change, DiaObject *obj);
+static void group_prop_change_revert(GroupPropChange *change, DiaObject *obj);
+static void group_prop_change_free(GroupPropChange *change);
+
 static real group_distance_from(Group *group, Point *point);
 static void group_select(Group *group);
 static ObjectChange* group_move_handle(Group *group, Handle *handle, Point *to, ConnectionPoint *cp,
@@ -61,7 +76,7 @@
   (MoveFunc)            group_move,
   (MoveHandleFunc)      group_move_handle,
   (GetPropertiesFunc)   object_create_props_dialog,
-  (ApplyPropertiesFunc) object_apply_props_from_dialog,
+  (ApplyPropertiesFunc) group_apply_props_from_dialog,
   (ObjectMenuFunc)      NULL,
   (DescribePropsFunc)   group_describe_props,
   (GetPropsFunc)        group_get_props,
@@ -445,3 +460,95 @@
     }
   }
 }
+
+GroupPropChange *
+group_apply_props_from_dialog(Group *group, WIDGET *dialog_widget)
+{
+  PropDialog *dialog = prop_dialog_from_widget(dialog_widget);
+
+  prop_get_data_from_widgets(dialog);
+  return group_apply_props(group, dialog->props);
+}
+
+GroupPropChange *
+group_apply_props(Group *group, GPtrArray *props)
+{
+  GList *tmp = NULL;
+  GList *clist = NULL;
+  GroupPropChange *change = NULL;
+  change = g_new0(GroupPropChange, 1);
+
+
+  change->obj_change.apply =
+    (ObjectChangeApplyFunc) group_prop_change_apply;
+  change->obj_change.revert =
+    (ObjectChangeRevertFunc) group_prop_change_revert;
+  change->obj_change.free =
+    (ObjectChangeFreeFunc) group_prop_change_free;
+
+  change->group = group;
+
+  for (tmp = group->objects; tmp != NULL; tmp = g_list_next(tmp)) {
+    DiaObject *obj = (DiaObject*)tmp->data;
+    ObjectChange *objchange = object_apply_props(obj, props);
+    clist = g_list_append(clist, objchange);
+  }
+
+  change->changes_per_object = clist;
+
+  return change;
+}
+
+static void
+group_prop_change_apply(GroupPropChange *change, DiaObject *obj)
+{
+  GList *tmp;
+
+  for (tmp = change->changes_per_object; tmp != NULL;
+       tmp = g_list_next(tmp)) {
+    ObjectChange *obj_change = (ObjectChange*)tmp->data;
+
+    /*
+      This call to apply() depends on the fact that it is actually a
+      call to object_prop_change_apply_revert(), which never uses its
+      second argument. This particular behaviour used in
+      ObjectPropChange is actually better than the behaviour implied
+      in ObjectChange. Read comments near the ObjectChange struct in
+      objchange.h
+     */
+    obj_change->apply(obj_change, NULL);
+  }
+}
+
+static void
+group_prop_change_revert(GroupPropChange *change, DiaObject *obj)
+{
+  GList *tmp;
+
+  for (tmp = change->changes_per_object; tmp != NULL;
+       tmp = g_list_next(tmp)) {
+    ObjectChange *obj_change = (ObjectChange*)tmp->data;
+
+    /*
+      This call to revert() depends on the fact that it is actually a
+      call to object_prop_change_apply_revert(), which never uses its
+      second argument. This particular behaviour used in
+      ObjectPropChange is actually better than the behaviour implied
+      in ObjectChange. Read comments near the ObjectChange struct in
+      objchange.h
+     */
+    obj_change->revert(obj_change, NULL);
+  }
+}
+
+static void group_prop_change_free(GroupPropChange *change)
+{
+  GList *tmp;
+  for (tmp = change->changes_per_object; tmp != NULL;
+       tmp = g_list_next(tmp)) {
+    ObjectChange *obj_change = (ObjectChange*)tmp->data;
+    obj_change->free(obj_change);
+    g_free(obj_change);
+  }
+  g_list_free(change->changes_per_object);
+}
