[dia] [transform] Optimize object_apply_props_from_dialog() and self-only property



commit e3bf3daa5e7271a44703b27621c00e8f0e51fa29
Author: Hans Breuer <hans breuer org>
Date:   Sat Sep 25 20:46:58 2010 +0200

    [transform] Optimize object_apply_props_from_dialog() and self-only property
    
    The new group::matrix property is not meant to be passed to group members.
    Only the Group itself should have it's matrix changed. Introduce
    PROP_FLAG_SELF_ONLY and use it to split the passed in property list
    for consumption by self or child list.
    Also there was room for optimization by actually only passing widget
    modified properties down from object_apply_props_from_dialog()

 lib/group.c      |   83 +++++++++++++++++++++++++++++++++++++++++++-----------
 lib/prop_basic.c |    3 ++
 lib/properties.h |    1 +
 lib/propobject.c |   21 +++++++++++--
 4 files changed, 88 insertions(+), 20 deletions(-)
---
diff --git a/lib/group.c b/lib/group.c
index a237016..b62ec4c 100644
--- a/lib/group.c
+++ b/lib/group.c
@@ -39,8 +39,6 @@ struct _Group {
   const PropDescription *pdesc;
   
   DiaMatrix *matrix;
-
-  gboolean self_only;
 };
 
 typedef struct _GroupPropChange GroupPropChange;
@@ -579,7 +577,7 @@ group_prop_event_deliver(Group *group, Property *prop)
 }
 
 static PropDescription _group_props[] = {
-  { "matrix", PROP_TYPE_MATRIX, PROP_FLAG_DONT_MERGE|PROP_FLAG_VISIBLE|PROP_FLAG_OPTIONAL|PROP_FLAG_NO_DEFAULTS,
+  { "matrix", PROP_TYPE_MATRIX, PROP_FLAG_SELF_ONLY|PROP_FLAG_DONT_MERGE|PROP_FLAG_VISIBLE|PROP_FLAG_OPTIONAL|PROP_FLAG_NO_DEFAULTS,
   N_("Transformation"), NULL, NULL },
 
   PROP_DESC_END
@@ -634,40 +632,71 @@ static void
 group_get_props(Group *group, GPtrArray *props)
 {
   GList *tmp;
+  GPtrArray *props_list, *props_self;
+  int i;
 
-  /* FIXME: need to somehow avoid to ask included groups for matrix, too. */
-  object_get_props_from_offsets(&group->object, _group_offsets, props);
+  /* Need to split the passed in properties to self props
+   * and the ones really passed to the list of owned objects.
+   */
+  props_self = g_ptr_array_new();
+  props_list = g_ptr_array_new();
+  for (i=0; i < props->len; i++) {
+    Property *p = g_ptr_array_index(props,i);
+
+    if ((p->descr->flags & PROP_FLAG_SELF_ONLY) != 0)
+      g_ptr_array_add(props_self, p);
+    else
+      g_ptr_array_add(props_list, p);
+  }
 
-  if (group->self_only)
-    return;
+  object_get_props_from_offsets(&group->object, _group_offsets, props_self);
 
   for (tmp = group->objects; tmp != NULL; tmp = tmp->next) {
     DiaObject *obj = tmp->data;
 
     if (obj->ops->get_props) {
-      obj->ops->get_props(obj, props);
+      obj->ops->get_props(obj, props_list);
     }
   }
+
+  g_ptr_array_free(props_list, TRUE);
+  g_ptr_array_free(props_self, TRUE);
 }
 
 static void
 group_set_props(Group *group, GPtrArray *props)
 {
   GList *tmp;
+  GPtrArray *props_list, *props_self;
+  int i;
 
-  /* FIXME: need to somehow avoid to set included groups for matrix, too. */
-  object_set_props_from_offsets(&group->object, _group_offsets, props);
+  /* Need to split the passed in properties to self props
+   * and the ones really passed to the list of owned objects.
+   */
+  props_self = g_ptr_array_new();
+  props_list = g_ptr_array_new();
+  for (i=0; i < props->len; i++) {
+    Property *p = g_ptr_array_index(props,i);
+
+    if ((p->descr->flags & PROP_FLAG_SELF_ONLY) != 0)
+      g_ptr_array_add(props_self, p);
+    else
+      g_ptr_array_add(props_list, p);
+  }
 
-  if (group->self_only)
-    return;
+  object_set_props_from_offsets(&group->object, _group_offsets, props_self);
 
   for (tmp = group->objects; tmp != NULL; tmp = tmp->next) {
     DiaObject *obj = tmp->data;
 
     if (obj->ops->set_props) {
-      obj->ops->set_props(obj, props);
+      obj->ops->set_props(obj, props_list);
     }
   }
+
+  g_ptr_array_free(props_list, TRUE);
+  g_ptr_array_free(props_self, TRUE);
+
   group_update_data (group);
 }
 
@@ -678,6 +707,9 @@ group_apply_properties_list(Group *group, GPtrArray *props)
   GList *clist = NULL;
   ObjectChange *objchange;
   GroupPropChange *change = NULL;
+  GPtrArray *props_list, *props_self;
+  int i;
+
   change = g_new0(GroupPropChange, 1);
 
 
@@ -690,19 +722,36 @@ group_apply_properties_list(Group *group, GPtrArray *props)
 
   change->group = group;
 
+  /* Need to split the passed in properties to self props
+   * and the ones really passed to the list of owned objects.
+   */
+  props_self = g_ptr_array_new();
+  props_list = g_ptr_array_new();
+  for (i=0; i < props->len; ++i) {
+    Property *p = g_ptr_array_index(props,i);
+
+    if (p->experience & PXP_NOTSET)
+      continue;
+    else if ((p->descr->flags & PROP_FLAG_SELF_ONLY) != 0)
+      g_ptr_array_add(props_self, p);
+    else
+      g_ptr_array_add(props_list, p);
+  }
+
   for (tmp = group->objects; tmp != NULL; tmp = g_list_next(tmp)) {
     DiaObject *obj = (DiaObject*)tmp->data;
     objchange = NULL;
     
-    objchange = obj->ops->apply_properties_list(obj, props);
+    objchange = obj->ops->apply_properties_list(obj, props_list);
     clist = g_list_append(clist, objchange);
   }
   /* finally ourself */
-  group->self_only = TRUE;
-  objchange = object_apply_props (&group->object, props);
-  group->self_only = FALSE;
+  objchange = object_apply_props (&group->object, props_self);
   clist = g_list_append(clist, objchange);
 
+  g_ptr_array_free(props_list, TRUE);
+  g_ptr_array_free(props_self, TRUE);
+
   group_update_data (group);
 
   change->changes_per_object = clist;
diff --git a/lib/prop_basic.c b/lib/prop_basic.c
index 6aa53a9..4d320aa 100644
--- a/lib/prop_basic.c
+++ b/lib/prop_basic.c
@@ -129,6 +129,9 @@ static void
 commonprop_reset_widget(Property *prop, WIDGET *widget)
 {
   prop->real_ops->reset_widget(prop,widget);
+  /* reset widget ususally emits the change signal on property,
+   * but the property itself did not change */
+  prop->experience |= PXP_NOTSET;
   prop->experience |= PXP_RESET_WIDGET;
 }
 
diff --git a/lib/properties.h b/lib/properties.h
index 4b84c92..6f55e0c 100644
--- a/lib/properties.h
+++ b/lib/properties.h
@@ -240,6 +240,7 @@ struct _PropDescription {
 #define PROP_FLAG_MULTIVALUE 0x0040 /* Multiple values for prop in group */
 #define PROP_FLAG_WIDGET_ONLY 0x0080 /* only cosmetic property, no data */
 #define PROP_FLAG_OPTIONAL 0x0100 /* don't complain if it does not exist */
+#define PROP_FLAG_SELF_ONLY 0x0200 /* do not apply to object lists */
 
 typedef enum {PROP_UNION, PROP_INTERSECTION} PropMergeOption;
 
diff --git a/lib/propobject.c b/lib/propobject.c
index 0dd81bc..2f9d268 100644
--- a/lib/propobject.c
+++ b/lib/propobject.c
@@ -203,15 +203,30 @@ object_list_create_props_dialog(GList *objects, gboolean is_default)
 ObjectChange *
 object_apply_props_from_dialog(DiaObject *obj, WIDGET *dialog_widget)
 {
+  ObjectChange *change;
   PropDialog *dialog = prop_dialog_from_widget(dialog_widget);
+  GPtrArray *props = g_ptr_array_new ();
+  int i;
 
   prop_get_data_from_widgets(dialog);
+  /* only stuff which is actually changed */
+  for (i = 0; i < dialog->props->len; ++i) {
+    Property *p = g_ptr_array_index (dialog->props, i);
+    if (p->descr->flags & PROP_FLAG_WIDGET_ONLY)
+      continue;
+    if ((p->experience & PXP_NOTSET) == 0)
+      g_ptr_array_add(props, p);
+  }
+
   if (!obj->ops->apply_properties_list) {
     g_warning("using a fallback function to apply properties;"
               " undo may not work correctly");
-    return object_apply_props(obj, dialog->props);
-  } else
-    return obj->ops->apply_properties_list(obj, dialog->props);
+    change = object_apply_props(obj, props);
+  } else {
+    change = obj->ops->apply_properties_list(obj, props);
+  }
+  g_ptr_array_free(props, TRUE);
+  return change;
 }
 
 gboolean



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]