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

gEDA-user: unpromoted visible attributes



Hi all,

I'm working on a patch to libgeda and got in a little over my head so
wanted to get some help/feedback...

I wanted to make it possible to not promote visible attributes, as
previously, all visible attributes were automatically promoted.  This
was annoying if say, I wanted the part number or description for some
symbol to be visible on the schematic, but remain unpromoted as part
of the project-global symbol so I could tweak it in one place if
things changed.

So I went ahead and added a promote-visible flag parallel to the
promote-invisible flag, then in o_complex_is_eligible_attribute(), if
promote-visible is false and the attribute isn't in
always-promote-attributes, then don't promote it, even if it is
visible.

The problem is when a schematic file was being loaded, and a complex
object read in, only attributes that were "promotable", as defined by
o_complex_is_eligible_attribute(), were marked invisible or deleted
since there would be a schematic-level attribute coming up for it.
This meant that an attribute that was promoted manually, but not
identified as "promotable", would end up with two copies, the copy
from the complex because it wasn't "promotable" and the copy from the
schematic that was added when it was promoted.  This wasn't visible
when all visible attributes were promotable, but now that a visible
attribute could be unpromotable this would cause two visible copies of
the manually promoted attribute to appear, clearly wrong.

The fix was to check for attributes that were actually promoted,
instead of those that were just promotable, and hide/remove those.  Of
course this can't happen until the attached attributes are read in,
not at the point the complex is loaded.  So I changed
o_complex_remove_promotable_attribs() to
o_complex_remove_promoted_attribs() (and changed the functionality to
match the changed name), and called it in a_basic.c:o_read_buffer()
after the attached attributes were read in instead of
o_complex.c:o_complex_read().

Another hiccup was when a complex is copied.  Previously,
o_complex_remove_promotable_attribs() was called on the newly copied
complex, which didn't make much sense to me since the source complex
would already have them hidden or removed.  The problem is (I think
this was a problem before?) if the complex is copied, but the attached
attributes aren't, then the copy will be missing (or have invisible)
attributes that the user would probably expect to be there.  This
seems like a minor issue though.  In any case, I removed the
o_complex_remove_promotable_attribs() call from o_complex_copy().

So this all seems right and okay to me, but I'm not super familiar
with the code, so if anyone has any feedback I would appreciate it.
What side affects might this have that I haven't checked for?  Can I
assume that if an attribute attached to complex has the same name as
one inside the complex, that it is a "promoted" version of that
attribute and the internal one should be hidden or removed? I'll
attach a copy of the patch that seems to be working for me.

Thanks,

Jared
From 186ebda9e61afde11700fbfcb772e2d26c2b66e8 Mon Sep 17 00:00:00 2001
From: Jared Casper <jaredcasper@xxxxxxxxx>
Date: Wed, 21 Oct 2009 22:41:23 -0700
Subject: [PATCH] Add promote-visible flag to libgeda.

Previously, there was no way to only promote only some visible
attributes when a component is instantiated, because if attribute
promotion was on at all, all visible attributes would be promoted.
With the promote-visible flag set to true, the old behavior exists.
With it set to false, it is possible to completely specify exactly
what attributes are promoted using always-promote-attributes (minus
symversion).

The caused a problem when a schematic file was being loaded, and a
complex object read in, the attributes that were "promotable" were
marked invisible or deleted since there would be a schematic-level
attribute coming up for it.  This meant that an attribute that was
promoted manually, but not identified as "promotable" by
o_complex_is_eligible_attribute(), would end up with two copies, the
copy from the complex because it wasn't "promotable" and the copy from
the schematic that was added when it was promoted.  This wasn't
visible when all visible attributes were "promotable", but now that a
visible attribute could be "unpromotable" this would cause two visible
copies of the manually promoted attribute to appear, clearly wrong.

The fix was to check for attributes that were actually promoted,
instead of those that were just promotable, and hide/remove those.  Of
course this can't happen until the attached attributes are read in,
not at the point the complex is loaded.  So I changed
o_complex_remove_promotable_attribs() to
o_complex_remove_promoted_attribs() (and changed the functionality to
match the changed name), and called it in a_basic.c:o_read_buffer()
after the attached attributes were read in instead of
o_complex.c:o_complex_read().
---
 libgeda/include/i_vars_priv.h    |    1 +
 libgeda/include/libgeda/struct.h |    3 ++
 libgeda/include/prototype_priv.h |    2 +
 libgeda/lib/system-gafrc         |   10 +++++
 libgeda/src/a_basic.c            |    4 ++
 libgeda/src/g_rc.c               |   17 +++++++++
 libgeda/src/g_register.c         |    7 ++--
 libgeda/src/i_vars.c             |    2 +
 libgeda/src/o_complex_basic.c    |   75 +++++++++++++++++++++++++++++---------
 libgeda/src/s_toplevel.c         |    1 +
 10 files changed, 102 insertions(+), 20 deletions(-)

diff --git a/libgeda/include/i_vars_priv.h b/libgeda/include/i_vars_priv.h
index b10047f..726e56e 100644
--- a/libgeda/include/i_vars_priv.h
+++ b/libgeda/include/i_vars_priv.h
@@ -13,5 +13,6 @@ extern GList *default_always_promote_attributes;
 
 extern int default_attribute_promotion;
 extern int default_promote_invisible;
+extern int default_promote_visible;
 extern int default_keep_invisible;
 
diff --git a/libgeda/include/libgeda/struct.h b/libgeda/include/libgeda/struct.h
index c06a11f..b73a562 100644
--- a/libgeda/include/libgeda/struct.h
+++ b/libgeda/include/libgeda/struct.h
@@ -524,6 +524,9 @@ struct st_toplevel {
   /* controls if invisible attribs are promoted */
   int promote_invisible; 
 
+  /* controls if visible attribs are promoted */
+  int promote_visible;
+
   /* controls if invisible attribs are kept and not deleted */
   int keep_invisible;   
 
diff --git a/libgeda/include/prototype_priv.h b/libgeda/include/prototype_priv.h
index fce2c75..b018add 100644
--- a/libgeda/include/prototype_priv.h
+++ b/libgeda/include/prototype_priv.h
@@ -30,6 +30,7 @@ SCM g_rc_postscript_prolog(SCM scmsymname);
 SCM g_rc_map_font_character_to_file(SCM character_param, SCM file_param);
 SCM g_rc_attribute_promotion(SCM mode);
 SCM g_rc_promote_invisible(SCM mode);
+SCM g_rc_promote_visible(SCM mode);
 SCM g_rc_keep_invisible(SCM mode);
 SCM g_rc_always_promote_attributes(SCM scmsymname);
 SCM g_rc_print_color_map (SCM scm_map);
@@ -156,6 +157,7 @@ gboolean o_circle_get_position(TOPLEVEL *toplevel, gint *x, gint *y, OBJECT *obj
 void o_circle_recalc(TOPLEVEL *toplevel, OBJECT *o_current);
 
 /* o_complex_basic.c */
+void o_complex_remove_promoted_attribs (TOPLEVEL *toplevel, OBJECT *object);
 OBJECT *o_complex_read(TOPLEVEL *toplevel, char buf[], unsigned int release_ver, unsigned int fileformat_ver);
 char *o_complex_save(OBJECT *object);
 double o_complex_shortest_distance(OBJECT *object, int x, int y, int force_soild);
diff --git a/libgeda/lib/system-gafrc b/libgeda/lib/system-gafrc
index f238fb1..75b7363 100644
--- a/libgeda/lib/system-gafrc
+++ b/libgeda/lib/system-gafrc
@@ -60,6 +60,16 @@
 ;(promote-invisible "enabled")
 (promote-invisible "disabled")
 
+; promote-visible string
+;
+; If attribute-promotion is enabled, then this controls if visible floating
+; attributes are promoted (attached to the outside of the component) if the
+; text string is visible.  This is usually what you want, so the default is
+; enabled.
+;
+(promote-visible "enabled")
+;(promote-invisible "disabled")
+
 ; keep-invisible string
 ;
 ; If both attribute-promotion and promote-invisible are enabled, then this 
diff --git a/libgeda/src/a_basic.c b/libgeda/src/a_basic.c
index 0c41d88..373342d 100644
--- a/libgeda/src/a_basic.c
+++ b/libgeda/src/a_basic.c
@@ -408,6 +408,10 @@ GList *o_read_buffer (TOPLEVEL *toplevel, GList *object_list,
           /* yes */
           /* verify symbol version (not file format but rather contents) */
           o_complex_check_symversion(toplevel, last_complex);
+
+          /* Delete or hide attributes that are promoted */
+          o_complex_remove_promoted_attribs (toplevel, last_complex);
+
           last_complex = NULL;
         }
 
diff --git a/libgeda/src/g_rc.c b/libgeda/src/g_rc.c
index a5c7c35..6835d63 100644
--- a/libgeda/src/g_rc.c
+++ b/libgeda/src/g_rc.c
@@ -875,6 +875,23 @@ SCM g_rc_promote_invisible(SCM mode)
  *  \par Function Description
  *
  */
+SCM g_rc_promote_visible(SCM mode)
+{
+  static const vstbl_entry mode_table[] = {
+    {TRUE , "enabled" },
+    {FALSE, "disabled"},
+  };
+
+  RETURN_G_RC_MODE("promote-visible",
+		   default_promote_visible,
+		   2);
+}
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
 SCM g_rc_keep_invisible(SCM mode)
 {
   static const vstbl_entry mode_table[] = {
diff --git a/libgeda/src/g_register.c b/libgeda/src/g_register.c
index f1f1d90..633763a 100644
--- a/libgeda/src/g_register.c
+++ b/libgeda/src/g_register.c
@@ -66,9 +66,10 @@ static struct gsubr_t libgeda_funcs[] = {
   { "bitmap-directory",         1, 0, 0, g_rc_bitmap_directory },
   { "bus-ripper-symname",       1, 0, 0, g_rc_bus_ripper_symname },
   { "postscript-prolog",        1, 0, 0, g_rc_postscript_prolog },
-  { "attribute-promotion",       1, 0, 0, g_rc_attribute_promotion },
-  { "promote-invisible",         1, 0, 0, g_rc_promote_invisible },
-  { "keep-invisible",            1, 0, 0, g_rc_keep_invisible },
+  { "attribute-promotion",      1, 0, 0, g_rc_attribute_promotion },
+  { "promote-invisible",        1, 0, 0, g_rc_promote_invisible },
+  { "promote-visible",          1, 0, 0, g_rc_promote_visible },
+  { "keep-invisible",           1, 0, 0, g_rc_keep_invisible },
   { "always-promote-attributes",1, 0, 0, g_rc_always_promote_attributes },
   { "print-color-map", 0, 1, 0, g_rc_print_color_map },
   { NULL,                       0, 0, 0, NULL } };
diff --git a/libgeda/src/i_vars.c b/libgeda/src/i_vars.c
index 24c03c7..9c69d30 100644
--- a/libgeda/src/i_vars.c
+++ b/libgeda/src/i_vars.c
@@ -54,6 +54,7 @@ GList *default_always_promote_attributes = NULL;
 
 int   default_attribute_promotion = TRUE;
 int   default_promote_invisible = FALSE;
+int   default_promote_visible = TRUE;
 int   default_keep_invisible = TRUE;
 
 /*! \brief Initialize variables in TOPLEVEL object
@@ -72,6 +73,7 @@ void i_vars_libgeda_set(TOPLEVEL *toplevel)
 
   toplevel->attribute_promotion = default_attribute_promotion;
   toplevel->promote_invisible = default_promote_invisible;
+  toplevel->promote_visible = default_promote_visible;
   toplevel->keep_invisible = default_keep_invisible;
 
   /* copy the always_promote_attributes list from the default */
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index 3e2df60..03c3f8b 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -230,6 +230,10 @@ static int o_complex_is_eligible_attribute (TOPLEVEL *toplevel, OBJECT *object)
   if (object->visibility == INVISIBLE && toplevel->promote_invisible == FALSE)
     return FALSE; /* attribute not eligible for promotion */
 
+  /* object is visible and we do not want to promote visible text */
+  if (object->visibility == VISIBLE && toplevel->promote_visible == FALSE)
+    return FALSE;
+
   /* yup, attribute can be promoted */
   return TRUE;
 }
@@ -356,13 +360,55 @@ GList *o_complex_promote_attribs (TOPLEVEL *toplevel, OBJECT *object)
 }
 
 
-/*! \brief Delete or hide promotable from the passed OBJECT
+/*! \brief Get attributes that have been promoted from inside a
+ *  complex (i.e. that are attached to the complex, and there is an
+ *  attribute of the same name in the complex)
+ *
+ *  \par Function Description
+ *  Returns a GList of OBJECTs which have been promoted from within
+ *  the passed complex OBJECT.  The primitive OBJECT inside the
+ *  complex, not the promoted, outside OBJECT, is returned.
+ *
+ *  \param [in]  toplevel The toplevel environment.
+ *  \param [in]  object   The complex object being modified.
+ *  \returns              A linked list of OBJECTs to promote.
+ */
+static GList *o_complex_get_promoted (TOPLEVEL *toplevel, OBJECT *object, int detach)
+{
+  GList *promoted = NULL;
+  GList *iter;
+  GList *prim_attribs;
+  OBJECT *a_current;
+  char *name;
+  OBJECT *matched_prim;
+
+  prim_attribs = o_attrib_find_floating_attribs (object->complex->prim_objs);
+
+  for (iter = object->attribs; iter != NULL; iter = g_list_next (iter)) {
+    a_current = iter->data;
+
+    if (!o_attrib_get_name_value(a_current, &name, NULL))
+      continue;
+
+    /* Is this attribute also a primitive of the complex? */
+    matched_prim = o_attrib_find_attrib_by_name(prim_attribs, name, 0);
+
+    if (matched_prim)
+      promoted = g_list_prepend (promoted, matched_prim);
+  }
+
+  promoted = g_list_reverse (promoted);
+  return promoted;
+}
+
+
+/*! \brief Delete or hide promoted from the passed OBJECT
  *
  *  \par Function Description
- *  Deletes or hides promotable attributes from the passed OBJECT.
+ *  Deletes or hides promoted attributes from the passed OBJECT.
  *  This is used when loading symbols during the load of a schematic from
  *  disk. The schematic will already contain local copies of symbol's
- *  promotable objects, so we delete or hide the symbol's copies.
+ *  promoted objects, so we delete or hide the symbol's copies.
  *
  *  Deletion / hiding is dependant on the setting of
  *  toplevel->keep_invisible. If true, attributes eligible for
@@ -371,27 +417,27 @@ GList *o_complex_promote_attribs (TOPLEVEL *toplevel, OBJECT *object)
  *  \param [in]  toplevel The toplevel environment.
  *  \param [in]  object   The complex object being altered.
  */
-static void o_complex_remove_promotable_attribs (TOPLEVEL *toplevel, OBJECT *object)
+void o_complex_remove_promoted_attribs (TOPLEVEL *toplevel, OBJECT *object)
 {
-  GList *promotable, *iter;
+  GList *promoted, *iter;
 
-  promotable = o_complex_get_promotable (toplevel, object, FALSE);
+  promoted = o_complex_get_promoted (toplevel, object, FALSE);
 
-  if (promotable == NULL)
+  if (promoted == NULL)
     return;
 
-  for (iter = promotable; iter != NULL; iter = g_list_next (iter)) {
+  for (iter = promoted; iter != NULL; iter = g_list_next (iter)) {
     OBJECT *a_object = iter->data;
-    if (toplevel->keep_invisible == TRUE) {   /* Hide promotable attributes */
+    if (toplevel->keep_invisible == TRUE) {   /* Hide promoted attributes */
       a_object->visibility = INVISIBLE;
-    } else {                                /* Delete promotable attributes */
+    } else {                                /* Delete promoted attributes */
       object->complex->prim_objs =
         g_list_remove (object->complex->prim_objs, a_object);
       s_delete_object (toplevel, a_object);
     }
   }
 
-  g_list_free (promotable);
+  g_list_free (promoted);
 }
 
 
@@ -655,7 +701,7 @@ void o_complex_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
  *  \par Function Description
  *  This function reads a complex object from the buffer \a buf.
  *  If the complex object was read successfully, a new object is
- *  allocated and appended to the \a object_list.
+ *  allocated and returned.
  *  
  *  \param [in] toplevel     The TOPLEVEL object
  *  \param [in] object_list  list of OBJECTS to append a new net
@@ -722,8 +768,6 @@ OBJECT *o_complex_read (TOPLEVEL *toplevel,
                                 x1, y1, 
                                 angle, mirror, clib,
                                 basename, selectable);
-    /* Delete or hide attributes eligible for promotion inside the complex */
-     o_complex_remove_promotable_attribs (toplevel, new_obj);
   }
 
   return new_obj;
@@ -832,9 +876,6 @@ OBJECT *o_complex_copy(TOPLEVEL *toplevel, OBJECT *o_current)
   /* Recalculate bounds */
   o_complex_recalc(toplevel, o_new);
 
-  /* Delete or hide attributes eligible for promotion inside the complex */
-  o_complex_remove_promotable_attribs (toplevel, o_new);
-
   s_slot_update_object (toplevel, o_new);
 
   /* deal with stuff that has changed */
diff --git a/libgeda/src/s_toplevel.c b/libgeda/src/s_toplevel.c
index 0b0829b..c7cebcb 100644
--- a/libgeda/src/s_toplevel.c
+++ b/libgeda/src/s_toplevel.c
@@ -107,6 +107,7 @@ TOPLEVEL *s_toplevel_new (void)
   /* for the following variables */
   toplevel->attribute_promotion = FALSE;
   toplevel->promote_invisible   = FALSE;
+  toplevel->promote_visible     = FALSE;
   toplevel->keep_invisible      = FALSE;
 
   toplevel->print_output_type = 0;
-- 
1.6.5.1


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user