Code

* src/widgets/toolbox.cpp, src/widgets/desktop-widget.cpp,
authormjwybrow <mjwybrow@users.sourceforge.net>
Fri, 20 Jan 2006 04:12:21 +0000 (04:12 +0000)
committermjwybrow <mjwybrow@users.sourceforge.net>
Fri, 20 Jan 2006 04:12:21 +0000 (04:12 +0000)
      src/conn-avoid-ref.cpp, src/conn-avoid-ref.h, src/sp-namedview.cpp,
      src/sp-namedview.h, src/attributes.cpp, src/attributes.h,
      src/attributes-test.cpp:

      Added a "Spacing" control to the connector toolbar which allows
      the user to adjust the amount of space left around avoided shapes
      for the purpose of determining auto-routing connector paths.

ChangeLog
src/attributes-test.cpp
src/attributes.cpp
src/attributes.h
src/conn-avoid-ref.cpp
src/conn-avoid-ref.h
src/sp-namedview.cpp
src/sp-namedview.h
src/widgets/desktop-widget.cpp
src/widgets/toolbox.cpp

index bc0b8a9ee375a3e26ab06dfdfa879327c0d00b84..bfd75e1ae2b4835b64af8c2f29afc50dd6244de5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,22 @@
-2006-01-15 Marco Scholten <mscholtn@xs4all.nl>
+2006-01-20  Michael Wybrow  <mjwybrow@users.sourceforge.net>
 
-    * /src/ui/dialog/inkscape-preferences.cpp
+       * src/widgets/toolbox.cpp, src/widgets/desktop-widget.cpp,
+         src/conn-avoid-ref.cpp, src/conn-avoid-ref.h, src/sp-namedview.cpp,
+         src/sp-namedview.h, src/attributes.cpp, src/attributes.h,
+         src/attributes-test.cpp:
+
+         Added a "Spacing" control to the connector toolbar which allows
+         the user to adjust the amount of space left around avoided shapes
+         for the purpose of determining auto-routing connector paths.
+
+2006-01-17  Marco Scholten  <mscholtn@xs4all.nl>
+
+       * /src/ui/dialog/inkscape-preferences.cpp:
       Added style swatches,
       Changed Gtk::Requisition Gtk::Widget::size_request() to  
       void Gtk::Widget::size_request(const Requisition& requisition)   
-    * /src/ui/dialog/preferences-widget.cpp & .h
-      Added DialogPage::set_tip()
+       * /src/ui/dialog/preferences-widget.cpp & .h:
+         Added DialogPage::set_tip()
 
 2006-01-17  Michael Wybrow  <mjwybrow@users.sourceforge.net>
 
@@ -18,7 +29,7 @@
        * src/svg/Makefile_insert: Updated to reflect a previous header
          file renaming.
 
-2006-01-12 Marco Scholten <mscholtn@xs4all.nl>
+2006-01-12  Marco Scholten  <mscholtn@xs4all.nl>
 
        * /src/ui/dialog/inkscape-preferences.cpp & .h:
          Converted preferences dialog to gtkmm
index 50d2e81bd32a1607d0b43f681748a74000602395..f40200c1f3f9bba60d1b9edec8dc8329163f677d 100644 (file)
@@ -323,6 +323,7 @@ static struct {char const *attr; bool supported;} const all_attrs[] = {
     {"inkscape:connection-start", true},
     {"inkscape:connection-end", true},
     {"inkscape:connector-avoid", true},
+    {"inkscape:connector-spacing", true},
     {"sodipodi:cx", true},
     {"sodipodi:cy", true},
     {"sodipodi:rx", true},
index 4d182179c7a7e873cde6b8e4f8354394f4fa6e0b..ce9c0e105230021bd845b4c194058f5008316b17 100644 (file)
@@ -100,6 +100,7 @@ static SPStyleProp const props[] = {
     {SP_ATTR_INKSCAPE_OBJECT_NODES, "inkscape:object-nodes"},
     {SP_ATTR_INKSCAPE_CURRENT_LAYER, "inkscape:current-layer"},
     {SP_ATTR_INKSCAPE_DOCUMENT_UNITS, "inkscape:document-units"},
+    {SP_ATTR_INKSCAPE_CONNECTOR_SPACING, "inkscape:connector-spacing"},
     /* SPGuide */
     {SP_ATTR_ORIENTATION, "orientation"},
     {SP_ATTR_POSITION, "position"},
index 24b87fc1c6d5eb80f00e7bdd75ea869d5378391f..2b4a68f34d520c2a8820a7bd3c12d215cd4b1623 100644 (file)
@@ -101,6 +101,7 @@ enum SPAttributeEnum {
     SP_ATTR_INKSCAPE_OBJECT_NODES,
     SP_ATTR_INKSCAPE_CURRENT_LAYER,
     SP_ATTR_INKSCAPE_DOCUMENT_UNITS,
+    SP_ATTR_INKSCAPE_CONNECTOR_SPACING,
     /* SPGuide */
     SP_ATTR_ORIENTATION,
     SP_ATTR_POSITION,
index 0dbd8c730156e51648bd7843e484ed5caaea7ac0..6575609022ba557f48479756250e90ed29b299af 100644 (file)
 #include "libavoid/incremental.h"
 #include "xml/simple-node.cpp"
 #include "document.h"
+#include "prefs-utils.h"
+
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "sp-namedview.h"
+#include "inkscape.h"
 
 
 static Avoid::Polygn avoid_item_poly(SPItem const *item);
-static void avoid_item_move(NR::Matrix const *mp, SPItem *moved_item);
 
 
 SPAvoidRef::SPAvoidRef(SPItem *spitem)
@@ -61,6 +66,11 @@ void SPAvoidRef::setAvoid(char const *value)
 
 void SPAvoidRef::handleSettingChange(void)
 {
+    SPDesktop *desktop = inkscape_active_desktop();
+    if (desktop == NULL) {
+        return;
+    }
+    
     if (new_setting == setting) {
         // Don't need to make any changes
         return;
@@ -100,6 +110,9 @@ void SPAvoidRef::handleSettingChange(void)
 
 static Avoid::Polygn avoid_item_poly(SPItem const *item)
 {
+    SPDesktop *desktop = inkscape_active_desktop();
+    g_assert(desktop != NULL);
+
     Avoid::Polygn poly;
 
     // TODO: The right way to do this is to return the convex hull of
@@ -116,9 +129,12 @@ static Avoid::Polygn avoid_item_poly(SPItem const *item)
     sp_document_ensure_up_to_date(item->document);
     
     NR::Rect rHull = item->invokeBbox(sp_item_i2doc_affine(item));
-    
+
+
+    double spacing = desktop->namedview->connector_spacing;
+
     // Add a little buffer around the edge of each object.
-    NR::Rect rExpandedHull = NR::expand(rHull, -10.0); 
+    NR::Rect rExpandedHull = NR::expand(rHull, -spacing); 
     poly = Avoid::newPoly(4);
 
     for (unsigned n = 0; n < 4; ++n) {
@@ -151,7 +167,31 @@ static Avoid::Polygn avoid_item_poly(SPItem const *item)
 }
 
 
-static void avoid_item_move(NR::Matrix const *mp, SPItem *moved_item)
+GSList *get_avoided_items(GSList *list, SPObject *from, SPDesktop *desktop, 
+        bool initialised)
+{
+    for (SPObject *child = sp_object_first_child(SP_OBJECT(from)) ;
+            child != NULL; child = SP_OBJECT_NEXT(child) ) {
+        if (SP_IS_ITEM(child) &&
+            !desktop->isLayer(SP_ITEM(child)) &&
+            !SP_ITEM(child)->isLocked() && 
+            !desktop->itemIsHidden(SP_ITEM(child)) &&
+            (!initialised || SP_ITEM(child)->avoidRef->shapeRef)
+            )
+        {
+            list = g_slist_prepend (list, SP_ITEM(child));
+        }
+
+        if (SP_IS_ITEM(child) && desktop->isLayer(SP_ITEM(child))) {
+            list = get_avoided_items(list, child, desktop, initialised);
+        }
+    }
+
+    return list;
+}
+
+
+void avoid_item_move(NR::Matrix const *mp, SPItem *moved_item)
 {
     Avoid::ShapeRef *shapeRef = moved_item->avoidRef->shapeRef;
     g_assert(shapeRef);
@@ -163,7 +203,32 @@ static void avoid_item_move(NR::Matrix const *mp, SPItem *moved_item)
         Avoid::freePoly(poly);
     }
 }
+
+
+void init_avoided_shape_geometry(SPDesktop *desktop)
+{
+    // Don't count this as changes to the document,
+    // it is basically just llate initialisation.
+    SPDocument *document = SP_DT_DOCUMENT(desktop);
+    gboolean saved = sp_document_get_undo_sensitive(document);
+    sp_document_set_undo_sensitive(document, FALSE);
+    
+    bool initialised = false;
+    GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop,
+            initialised);
+
+    for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
+        SPItem *item = reinterpret_cast<SPItem *>(iter->data);
+        item->avoidRef->handleSettingChange();
+    }
+
+    if (items) {
+        g_slist_free(items);
+    }
+    sp_document_set_undo_sensitive(document, saved);
+}
+
+
 /*
   Local Variables:
   mode:c++
index 3b5e6d3b5747a80e74fd8be431fae8688730c53b..ac9295cf917450307ab3a3c23834d15ce04b6757 100644 (file)
@@ -42,6 +42,12 @@ private:
     sigc::connection _transformed_connection;
 };
 
+extern GSList *get_avoided_items(GSList *list, SPObject *from,
+        SPDesktop *desktop, bool initialised = true);
+extern void avoid_item_move(NR::Matrix const *mp, SPItem *moved_item);
+extern void init_avoided_shape_geometry(SPDesktop *desktop);
+
+static const double defaultConnSpacing = 10.0;
 
 #endif /* !SEEN_CONN_AVOID_REF */
 
index c6e6b872b7c69ac074ab9a7efeda14d7d857a6cf..32e713792a67521578027f825cb1a1bba3c92ce0 100644 (file)
@@ -31,8 +31,9 @@
 #include "sp-namedview.h"
 #include "prefs-utils.h"
 #include "desktop.h"
+#include "conn-avoid-ref.h" // for defaultConnSpacing.
 
-#include "isnan.h" //temp fox for isnan().  include last
+#include "isnan.h" //temp fix for isnan().  include last
 
 #define DEFAULTTOLERANCE 0.4
 #define DEFAULTGRIDCOLOR 0x3f3fff25
@@ -117,6 +118,8 @@ static void sp_namedview_init(SPNamedView *nv)
     
     nv->default_layer_id = 0;
     
+    nv->connector_spacing = defaultConnSpacing;
+    
     new (&nv->grid_snapper) Inkscape::GridSnapper(nv, 0);
     new (&nv->guide_snapper) Inkscape::GuideSnapper(nv, 0);
     new (&nv->object_snapper) Inkscape::ObjectSnapper(nv, 0);
@@ -176,6 +179,7 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape:
     sp_object_read_attr(object, "inkscape:object-paths");
     sp_object_read_attr(object, "inkscape:object-nodes");
     sp_object_read_attr(object, "inkscape:current-layer");
+    sp_object_read_attr(object, "inkscape:connector-spacing");
     
     /* Construct guideline list */
     
@@ -492,6 +496,11 @@ static void sp_namedview_set(SPObject *object, unsigned int key, const gchar *va
             nv->default_layer_id = value ? g_quark_from_string(value) : 0;
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
+       case SP_ATTR_INKSCAPE_CONNECTOR_SPACING:
+            nv->connector_spacing = value ? g_ascii_strtod(value, NULL) :
+                    defaultConnSpacing;
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
        case SP_ATTR_INKSCAPE_DOCUMENT_UNITS: {
             /* The default unit if the document doesn't override this: e.g. for files saved as
              * `plain SVG', or non-inkscape files, or files created by an inkscape 0.40 &
index f96207794ea7215ebb43afa025af7b0efa9f3d27..2265dd8639c56735a5aba573ef9c9cc6efc53a9c 100644 (file)
@@ -81,6 +81,8 @@ struct SPNamedView : public SPObjectGroup {
     bool has_abs_tolerance;
     
     GQuark default_layer_id;
+    
+    double connector_spacing;
 
     guint32 gridcolor;
     guint32 gridempcolor;
index f9a8b8f62e1e9fe6fcf24c56bf7f27ec8e419f5c..b7832658fddef7284ba656f0b0814dc65c631836 100644 (file)
@@ -46,6 +46,7 @@
 #include "ui/widget/selected-style.h"
 #include "sp-item.h"
 #include "dialogs/swatches.h"
+#include "conn-avoid-ref.h"
 
 #ifdef WITH_INKBOARD
 #endif
@@ -912,6 +913,10 @@ sp_desktop_widget_new (SPNamedView *namedview)
     dtw->desktop->init (namedview, dtw->canvas);
     inkscape_add_desktop (dtw->desktop);
 
+    // Add the shape geometry to libavoid for autorouting connectors.
+    // This needs desktop set for its spacing preferences.
+    init_avoided_shape_geometry(dtw->desktop);
+    
     dtw->selected_style->setDesktop(dtw->desktop);
 
     /* Once desktop is set, we can update rulers */
index 7ebbf7a85e409613661e2ec1a9eb66dbf78b2bc1..0e3bf206a8575270d1ff748ec85f521e607f92a9 100644 (file)
@@ -47,6 +47,8 @@
 #include "helper/unit-menu.h"
 #include "helper/units.h"
 
+#include "inkscape.h"
+#include "conn-avoid-ref.h"
 
 
 #include "select-toolbar.h"
@@ -789,7 +791,7 @@ sp_stb_magnitude_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
     // in turn, prevent listener from responding
     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
 
-    bool modmade = FALSE;
+    bool modmade = false;
 
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
     GSList const *items = selection->itemList();
@@ -828,7 +830,7 @@ sp_stb_proportion_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
     // in turn, prevent listener from responding
     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
 
-    bool modmade = FALSE;
+    bool modmade = false;
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
     GSList const *items = selection->itemList();
     for (; items != NULL; items = items->next) {
@@ -879,7 +881,7 @@ sp_stb_sides_flat_state_changed(GtkWidget *widget, GtkObject *tbl)
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
     GSList const *items = selection->itemList();
     GtkWidget *prop_widget = (GtkWidget*) g_object_get_data(G_OBJECT(tbl), "prop_widget");
-    bool modmade = FALSE;
+    bool modmade = false;
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
         gtk_widget_set_sensitive(GTK_WIDGET(prop_widget), FALSE);
         for (; items != NULL; items = items->next) {
@@ -925,7 +927,7 @@ sp_stb_rounded_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
     // in turn, prevent listener from responding
     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
 
-    bool modmade = FALSE;
+    bool modmade = false;
 
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
     GSList const *items = selection->itemList();
@@ -962,7 +964,7 @@ sp_stb_randomized_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
     // in turn, prevent listener from responding
     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
 
-    bool modmade = FALSE;
+    bool modmade = false;
 
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
     GSList const *items = selection->itemList();
@@ -1603,7 +1605,7 @@ sp_spl_tb_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const *value_n
 
     gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
 
-    bool modmade = FALSE;
+    bool modmade = false;
     for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
          items != NULL;
          items = items->next)
@@ -2098,7 +2100,7 @@ sp_arctb_startend_value_changed(GtkAdjustment *adj, GtkWidget *tbl, gchar const
 
     gchar* namespaced_name = g_strconcat("sodipodi:", value_name, NULL);
 
-    bool modmade = FALSE;
+    bool modmade = false;
     for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
          items != NULL;
          items = items->next)
@@ -2173,7 +2175,7 @@ sp_arctb_open_state_changed(GtkWidget *widget, GtkObject *tbl)
     // in turn, prevent listener from responding
     g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
 
-    bool modmade = FALSE;
+    bool modmade = false;
 
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
         for (GSList const *items = SP_DT_SELECTION(desktop)->itemList();
@@ -2991,11 +2993,89 @@ static void sp_connector_path_set_ignore(void)
 }
 
 
+static void connector_spacing_changed(GtkAdjustment *adj, GtkWidget *tbl)
+{
+    // quit if run by the _changed callbacks
+    if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+        return;
+    }
+        
+    SPDesktop *desktop = (SPDesktop *) gtk_object_get_data(GTK_OBJECT(tbl),
+            "desktop");
+    SPDocument *doc = SP_DT_DOCUMENT(desktop);
+
+    if (!sp_document_get_undo_sensitive(doc))
+    {
+        return;
+    }
+
+    // in turn, prevent callbacks from responding
+    g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
+    
+    double old_spacing = desktop->namedview->connector_spacing;
+        
+    Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
+    
+    sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value);
+    SP_OBJECT(desktop->namedview)->updateRepr();
+    
+    GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop);
+    for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) {
+        SPItem *item = reinterpret_cast<SPItem *>(iter->data);
+        avoid_item_move(&NR::identity(), item);
+    }
+
+    if (items) {
+        g_slist_free(items);
+    }
+    
+    sp_document_done(doc);
+
+    g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
+    
+    spinbutton_defocus(GTK_OBJECT(tbl));
+}
+
+
+static void connector_tb_event_attr_changed(Inkscape::XML::Node *repr,
+        gchar const *name, gchar const *old_value, gchar const *new_value,
+        bool is_interactive, gpointer data)
+{
+    GtkWidget *tbl = GTK_WIDGET(data);
+
+    if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+        return;
+    }
+    if (strcmp(name, "inkscape:connector-spacing") != 0) {
+        return;
+    }
+
+    GtkAdjustment *adj = (GtkAdjustment*)
+            gtk_object_get_data(GTK_OBJECT(tbl), "spacing");
+    gdouble spacing = defaultConnSpacing;
+    sp_repr_get_double(repr, "inkscape:connector-spacing", &spacing);
+    
+    gtk_adjustment_set_value(adj, spacing);
+}
+
+
+static Inkscape::XML::NodeEventVector connector_tb_repr_events = {
+    NULL, /* child_added */
+    NULL, /* child_removed */
+    connector_tb_event_attr_changed,
+    NULL, /* content_changed */
+    NULL  /* order_changed */
+};
+
+
 static GtkWidget *
 sp_connector_toolbox_new(SPDesktop *desktop)
 {
     GtkTooltips *tt = gtk_tooltips_new();
     GtkWidget *tbl = gtk_hbox_new(FALSE, 0);
+    
+    gtk_object_set_data(GTK_OBJECT(tbl), "dtw", desktop->canvas);
+    gtk_object_set_data(GTK_OBJECT(tbl), "desktop", desktop);
 
     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
             AUX_BETWEEN_BUTTON_GROUPS);
@@ -3008,8 +3088,47 @@ sp_connector_toolbox_new(SPDesktop *desktop)
             "connector_ignore", GTK_SIGNAL_FUNC(sp_connector_path_set_ignore),
             tt, _("Make connectors ignore selected objects"));
 
+    //  interval
+    gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE,
+            AUX_BETWEEN_BUTTON_GROUPS);
+
+    // Spacing spinbox
+    {
+        GtkWidget *object_spacing = sp_tb_spinbutton(_("Spacing:"),
+                _("The amount of space left around objects by auto-routing connectors"),
+                "tools.connector", "spacing", 10, NULL, tbl, TRUE,
+                "inkscape:connector-spacing", 0, 100, 1.0, 10.0,
+                connector_spacing_changed, 1, 0);
+
+        gtk_box_pack_start(GTK_BOX(tbl), object_spacing, FALSE, FALSE,
+                AUX_SPACING);
+    }
+
     gtk_widget_show_all(tbl);
+    sp_set_font_size_smaller (tbl);
+    
+    // Code to watch for changes to the connector-spacing attribute in
+    // the XML.
+    Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview);
+    g_assert(repr != NULL);
+        
+    Inkscape::XML::Node *oldrepr = (Inkscape::XML::Node *)
+            gtk_object_get_data(GTK_OBJECT(tbl), "repr");
+    
+    if (oldrepr) { // remove old listener
+        sp_repr_remove_listener_by_data(oldrepr, tbl);
+        Inkscape::GC::release(oldrepr);
+        oldrepr = NULL;
+        g_object_set_data(G_OBJECT(tbl), "repr", NULL);
+    }
 
+    if (repr) {
+        g_object_set_data(G_OBJECT(tbl), "repr", repr);
+        Inkscape::GC::anchor(repr);
+        sp_repr_add_listener(repr, &connector_tb_repr_events, tbl);
+        sp_repr_synthesize_events(repr, &connector_tb_repr_events, tbl);
+    }
+    
     return tbl;
 
 } // end of sp_connector_toolbox_new()