Code

NR::Maybe => boost::optional
[inkscape.git] / src / dialogs / stroke-style.cpp
index bab57b67906adeda000d66d8b3d06dc71894431a..ae387e5f84e6a2f004cf08813f3c7daca3a5e91c 100644 (file)
@@ -73,6 +73,19 @@ static void sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw);
 static void sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw);
 
 static void sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, SPDesktop *desktop, SPWidget *spw );
+static void sp_stroke_style_widget_transientize_callback(Inkscape::Application *inkscape,
+                                                         SPDesktop *desktop,
+                                                         SPWidget *spw );
+
+/** Marker selection option menus */
+static GtkWidget * marker_start_menu = NULL;
+static GtkWidget * marker_mid_menu = NULL;
+static GtkWidget * marker_end_menu = NULL;
+
+static SPObject *ink_extract_marker_name(gchar const *n);
+static void      ink_markers_menu_update(SPWidget* spw);
+
+static Inkscape::UI::Cache::SvgPreview svg_preview_cache;
 
 /**
  * Create the stroke style widget, and hook up all the signals.
@@ -101,6 +114,8 @@ sp_stroke_style_paint_widget_new(void)
 
     g_signal_connect (INKSCAPE, "change_subselection", G_CALLBACK (sp_stroke_style_widget_change_subselection), spw);
 
+    g_signal_connect (G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK (sp_stroke_style_widget_transientize_callback), spw );
+
     gtk_signal_connect(GTK_OBJECT(psel), "mode_changed",
                        GTK_SIGNAL_FUNC(sp_stroke_style_paint_mode_changed),
                        spw);
@@ -119,7 +134,7 @@ sp_stroke_style_paint_widget_new(void)
  * On construction, simply does an update of the stroke style paint object.
  */
 static void
-sp_stroke_style_paint_construct(SPWidget *spw, SPPaintSelector *psel)
+sp_stroke_style_paint_construct(SPWidget *spw, SPPaintSelector */*psel*/)
 {
 #ifdef SP_SS_VERBOSE
     g_print( "Stroke style widget constructed: inkscape %p repr %p\n",
@@ -127,17 +142,17 @@ sp_stroke_style_paint_construct(SPWidget *spw, SPPaintSelector *psel)
 #endif
     if (spw->inkscape) {
         sp_stroke_style_paint_update (spw);
-    } 
+    }
 }
 
 /**
  * On signal modified, invokes an update of the stroke style paint object.
  */
 static void
-sp_stroke_style_paint_selection_modified ( SPWidget *spw,
-                                        Inkscape::Selection *selection,
-                                        guint flags,
-                                        SPPaintSelector *psel)
+sp_stroke_style_paint_selection_modified( SPWidget *spw,
+                                          Inkscape::Selection */*selection*/,
+                                          guint flags,
+                                          SPPaintSelector */*psel*/ )
 {
     if (flags & ( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG |
                   SP_OBJECT_STYLE_MODIFIED_FLAG) ) {
@@ -150,9 +165,9 @@ sp_stroke_style_paint_selection_modified ( SPWidget *spw,
  * On signal selection changed, invokes an update of the stroke style paint object.
  */
 static void
-sp_stroke_style_paint_selection_changed ( SPWidget *spw,
-                                        Inkscape::Selection *selection,
-                                        SPPaintSelector *psel )
+sp_stroke_style_paint_selection_changed( SPWidget *spw,
+                                         Inkscape::Selection */*selection*/,
+                                         SPPaintSelector */*psel*/ )
 {
     sp_stroke_style_paint_update (spw);
 }
@@ -162,9 +177,9 @@ sp_stroke_style_paint_selection_changed ( SPWidget *spw,
  * On signal change subselection, invoke an update of the stroke style widget.
  */
 static void
-sp_stroke_style_widget_change_subselection ( Inkscape::Application *inkscape, 
-                                        SPDesktop *desktop,
-                                        SPWidget *spw )
+sp_stroke_style_widget_change_subselection( Inkscape::Application */*inkscape*/,
+                                            SPDesktop */*desktop*/,
+                                            SPWidget *spw )
 {
     sp_stroke_style_paint_update (spw);
 }
@@ -185,9 +200,9 @@ sp_stroke_style_paint_update (SPWidget *spw)
     SPPaintSelector *psel = SP_PAINT_SELECTOR(gtk_object_get_data(GTK_OBJECT(spw), "paint-selector"));
 
     // create temporary style
-    SPStyle *query = sp_style_new ();
+    SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
     // query into it
-    int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE); 
+    int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKE);
 
     switch (result) {
         case QUERY_STYLE_NOTHING:
@@ -204,14 +219,7 @@ sp_stroke_style_paint_update (SPWidget *spw)
             SPPaintSelectorMode pselmode = sp_style_determine_paint_selector_mode (query, false);
             sp_paint_selector_set_mode (psel, pselmode);
 
-            if (query->stroke.set && query->stroke.type == SP_PAINT_TYPE_COLOR) {
-                gfloat d[3];
-                sp_color_get_rgb_floatv (&query->stroke.value.color, d);
-                SPColor color;
-                sp_color_set_rgb_float (&color, d[0], d[1], d[2]);
-                sp_paint_selector_set_color_alpha (psel, &color, SP_SCALE24_TO_FLOAT (query->stroke_opacity.value));
-
-            } else if (query->stroke.set && query->stroke.type == SP_PAINT_TYPE_PAINTSERVER) {
+            if (query->stroke.set && query->stroke.isPaintserver()) {
 
                 SPPaintServer *server = SP_STYLE_STROKE_SERVER (query);
 
@@ -235,6 +243,9 @@ sp_stroke_style_paint_update (SPWidget *spw)
                     SPPattern *pat = pattern_getroot (SP_PATTERN (server));
                     sp_update_pattern_list (psel, pat);
                 }
+            } else if (query->stroke.set && query->stroke.isColor()) {
+                sp_paint_selector_set_color_alpha (psel, &query->stroke.value.color, SP_SCALE24_TO_FLOAT (query->stroke_opacity.value));
+
             }
             break;
         }
@@ -246,7 +257,7 @@ sp_stroke_style_paint_update (SPWidget *spw)
         }
     }
 
-    g_free (query);
+    sp_style_unref(query);
 
     gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE));
 }
@@ -256,7 +267,7 @@ sp_stroke_style_paint_update (SPWidget *spw)
  */
 static void
 sp_stroke_style_paint_mode_changed( SPPaintSelector *psel,
-                                    SPPaintSelectorMode mode,
+                                    SPPaintSelectorMode /*mode*/,
                                     SPWidget *spw )
 {
     if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
@@ -270,12 +281,12 @@ sp_stroke_style_paint_mode_changed( SPPaintSelector *psel,
     sp_stroke_style_paint_changed(psel, spw);
 }
 
-static gchar *undo_label_1 = "stroke:flatcolor:1";
-static gchar *undo_label_2 = "stroke:flatcolor:2";
-static gchar *undo_label = undo_label_1;
+static gchar const *const undo_label_1 = "stroke:flatcolor:1";
+static gchar const *const undo_label_2 = "stroke:flatcolor:2";
+static gchar const *undo_label = undo_label_1;
 
 /**
- * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK 
+ * When a drag callback occurs on a paint selector object, if it is a RGB or CMYK
  * color mode, then set the stroke opacity to psel's flat color.
  */
 static void
@@ -290,7 +301,7 @@ sp_stroke_style_paint_dragged(SPPaintSelector *psel, SPWidget *spw)
         case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
         {
             sp_paint_selector_set_flat_color (psel, SP_ACTIVE_DESKTOP, "stroke", "stroke-opacity");
-            sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE, 
+            sp_document_maybe_done (sp_desktop_document(SP_ACTIVE_DESKTOP), undo_label, SP_VERB_DIALOG_FILL_STROKE,
                                     _("Set stroke color"));
             break;
         }
@@ -340,7 +351,7 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
 
             sp_repr_css_attr_unref(css);
 
-            sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, 
+            sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
                              _("Remove stroke"));
             break;
         }
@@ -349,13 +360,13 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
         case SP_PAINT_SELECTOR_MODE_COLOR_CMYK:
         {
             sp_paint_selector_set_flat_color (psel, desktop, "stroke", "stroke-opacity");
-            sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE, 
+            sp_document_maybe_done (sp_desktop_document(desktop), undo_label, SP_VERB_DIALOG_FILL_STROKE,
                                     _("Set stroke color"));
 
             // on release, toggle undo_label so that the next drag will not be lumped with this one
             if (undo_label == undo_label_1)
                 undo_label = undo_label_2;
-            else 
+            else
                 undo_label = undo_label_1;
 
             break;
@@ -371,22 +382,22 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
                 if (!vector) {
                     /* No vector in paint selector should mean that we just changed mode */
 
-                    SPStyle *query = sp_style_new ();
-                    int result = objects_query_fillstroke ((GSList *) items, query, false); 
+                    SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
+                    int result = objects_query_fillstroke ((GSList *) items, query, false);
                     guint32 common_rgb = 0;
                     if (result == QUERY_STYLE_MULTIPLE_SAME) {
-                        if (query->fill.type != SP_PAINT_TYPE_COLOR) {
+                        if (!query->fill.isColor()) {
                             common_rgb = sp_desktop_get_color(desktop, false);
                         } else {
-                            common_rgb = sp_color_get_rgba32_ualpha(&query->stroke.value.color, 0xff);
+                            common_rgb = query->stroke.value.color.toRGBA32( 0xff );
                         }
                         vector = sp_document_default_gradient_vector(document, common_rgb);
                     }
-                    g_free (query);
+                    sp_style_unref(query);
 
                     for (GSList const *i = items; i != NULL; i = i->next) {
                         if (!vector) {
-                            sp_item_set_gradient(SP_ITEM(i->data), 
+                            sp_item_set_gradient(SP_ITEM(i->data),
                                                  sp_gradient_vector_for_object(document, desktop, SP_OBJECT(i->data), false),
                                                  gradient_type, false);
                         } else {
@@ -401,7 +412,7 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
                     }
                 }
 
-                sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, 
+                sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
                                  _("Set gradient on stroke"));
             }
             break;
@@ -430,7 +441,7 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
                              continue;
 
                          SPStyle *style = SP_OBJECT_STYLE (selobj);
-                         if (style && style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) {
+                         if (style && style->stroke.isPaintserver()) {
                              SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (selobj);
                              if (SP_IS_PATTERN (server) && pattern_getroot (SP_PATTERN(server)) == pattern)
                                  // only if this object's pattern is not rooted in our selected pattern, apply
@@ -445,7 +456,7 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
 
                 } // end if
 
-                sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, 
+                sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
                                   _("Set pattern on stroke"));
             } // end if
 
@@ -455,11 +466,18 @@ sp_stroke_style_paint_changed(SPPaintSelector *psel, SPWidget *spw)
             if (items) {
                     SPCSSAttr *css = sp_repr_css_attr_new ();
                     sp_repr_css_unset_property (css, "stroke");
+                    sp_repr_css_unset_property (css, "stroke-opacity");
+                    sp_repr_css_unset_property (css, "stroke-width");
+                    sp_repr_css_unset_property (css, "stroke-miterlimit");
+                    sp_repr_css_unset_property (css, "stroke-linejoin");
+                    sp_repr_css_unset_property (css, "stroke-linecap");
+                    sp_repr_css_unset_property (css, "stroke-dashoffset");
+                    sp_repr_css_unset_property (css, "stroke-dasharray");
 
                     sp_desktop_set_style (desktop, css);
                     sp_repr_css_attr_unref (css);
 
-                    sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE, 
+                    sp_document_done (document, SP_VERB_DIALOG_FILL_STROKE,
                                       _("Unset stroke"));
             }
             break;
@@ -507,8 +525,6 @@ static void sp_stroke_style_line_dash_changed(SPDashSelector *dsel,
 
 static void sp_stroke_style_update_marker_menus(SPWidget *spw, GSList const *objects);
 
-static SPObject *ink_extract_marker_name(gchar const *n);
-
 
 /**
  * Helper function for creating radio buttons.  This should probably be re-thought out
@@ -546,6 +562,16 @@ sp_stroke_radio_button(GtkWidget *tb, char const *icon,
 
 }
 
+static void
+sp_stroke_style_widget_transientize_callback(Inkscape::Application */*inkscape*/,
+                                             SPDesktop */*desktop*/,
+                                             SPWidget */*spw*/ )
+{
+// TODO:  Either of these will cause crashes sometimes
+//    sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
+//    ink_markers_menu_update(spw);
+}
+
 /**
  * Creates a copy of the marker named mname, determines its visible and renderable
  * area in menu_id's bounding box, and then renders it.  This allows us to fill in
@@ -554,7 +580,7 @@ sp_stroke_radio_button(GtkWidget *tb, char const *icon,
 static GtkWidget *
 sp_marker_prev_new(unsigned psize, gchar const *mname,
                    SPDocument *source, SPDocument *sandbox,
-                   gchar *menu_id, NRArena const *arena, unsigned visionkey, NRArenaItem *root)
+                   gchar const *menu_id, NRArena const */*arena*/, unsigned /*visionkey*/, NRArenaItem *root)
 {
     // Retrieve the marker named 'mname' from the source SVG document
     SPObject const *marker = source->getObjectById(mname);
@@ -562,7 +588,8 @@ sp_marker_prev_new(unsigned psize, gchar const *mname,
         return NULL;
 
     // Create a copy repr of the marker with id="sample"
-    Inkscape::XML::Node *mrepr = SP_OBJECT_REPR (marker)->duplicate();
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(sandbox);
+    Inkscape::XML::Node *mrepr = SP_OBJECT_REPR (marker)->duplicate(xml_doc);
     mrepr->setAttribute("id", "sample");
 
     // Replace the old sample in the sandbox by the new one
@@ -574,7 +601,7 @@ sp_marker_prev_new(unsigned psize, gchar const *mname,
     Inkscape::GC::release(mrepr);
 
 // Uncomment this to get the sandbox documents saved (useful for debugging)
-    //FILE *fp = fopen (g_strconcat(mname, ".svg", NULL), "w");
+    //FILE *fp = fopen (g_strconcat(menu_id, mname, ".svg", NULL), "w");
     //sp_repr_save_stream (sp_document_repr_doc (sandbox), fp);
     //fclose (fp);
 
@@ -587,20 +614,29 @@ sp_marker_prev_new(unsigned psize, gchar const *mname,
         return NULL; // sandbox broken?
 
     // Find object's bbox in document
-    NR::Matrix const i2doc(sp_item_i2doc_affine(SP_ITEM(object)));
-
-    NR::Rect const dbox = SP_ITEM(object)->invokeBbox(i2doc);
+    Geom::Matrix const i2doc(sp_item_i2doc_affine(SP_ITEM(object)));
+    boost::optional<NR::Rect> dbox = SP_ITEM(object)->getBounds(from_2geom(i2doc));
 
-    if (dbox.isEmpty()) {
+    if (!dbox) {
         return NULL;
     }
 
     /* Update to renderable state */
     double sf = 0.8;
-    GdkPixbuf* pixbuf = render_pixbuf(root, sf, dbox, psize);
+    GdkPixbuf* pixbuf = NULL;
+
+    gchar *cache_name = g_strconcat(menu_id, mname, NULL);
+    Glib::ustring key = svg_preview_cache.cache_key(source->uri, cache_name, psize);
+    g_free (cache_name);
+    pixbuf = svg_preview_cache.get_preview_from_cache(key);
+
+    if (pixbuf == NULL) {
+        pixbuf = render_pixbuf(root, sf, to_2geom(*dbox), psize);
+        svg_preview_cache.set_preview_in_cache(key, pixbuf);
+    }
 
     // Create widget
-    GtkWidget *pb = gtk_image_new_from_pixbuf(get_pixbuf(pixbuf));
+    GtkWidget *pb = gtk_image_new_from_pixbuf(pixbuf);
 
     return pb;
 }
@@ -635,7 +671,7 @@ ink_marker_list_get (SPDocument *source)
  * Adds previews of markers in marker_list to the given menu widget
  */
 static void
-sp_marker_menu_build (GtkWidget *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar *menu_id)
+sp_marker_menu_build (GtkWidget *m, GSList *marker_list, SPDocument *source, SPDocument *sandbox, gchar const *menu_id)
 {
     // Do this here, outside of loop, to speed up preview generation:
     NRArena const *arena = NRArena::create();
@@ -659,6 +695,7 @@ sp_marker_menu_build (GtkWidget *m, GSList *marker_list, SPDocument *source, SPD
         gtk_widget_show(hb);
 
         // generate preview
+
         GtkWidget *prv = sp_marker_prev_new (22, markid, source, sandbox, menu_id, arena, visionkey, root);
         gtk_widget_show(prv);
         gtk_box_pack_start(GTK_BOX(hb), prv, FALSE, FALSE, 6);
@@ -685,42 +722,15 @@ sp_marker_menu_build (GtkWidget *m, GSList *marker_list, SPDocument *source, SPD
  *
  */
 static void
-sp_marker_list_from_doc (GtkWidget *m, SPDocument *current_doc, SPDocument *source, SPDocument *markers_doc, SPDocument *sandbox, gchar *menu_id)
+sp_marker_list_from_doc (GtkWidget *m, SPDocument */*current_doc*/, SPDocument *source, SPDocument */*markers_doc*/, SPDocument *sandbox, gchar const *menu_id)
 {
     GSList *ml = ink_marker_list_get(source);
     GSList *clean_ml = NULL;
 
-    // Do this here, outside of loop, to speed up preview generation:
-    /* Create new arena */
-    NRArena const *arena = NRArena::create();
-    /* Create ArenaItem and set transform */
-    unsigned const visionkey = sp_item_display_key_new(1);
-    NRArenaItem *root =  sp_item_invoke_show( SP_ITEM(SP_DOCUMENT_ROOT (sandbox)), (NRArena *) arena, visionkey, SP_ITEM_SHOW_DISPLAY );
-
     for (; ml != NULL; ml = ml->next) {
         if (!SP_IS_MARKER(ml->data))
             continue;
 
-/*
-  Bug 980157 wants to have stock markers show up at the top of the dropdown menu
-  Thus we can skip all of this code, which simply looks for duplicate stock markers
-
-        Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) ml->data);
-        bool stock_dupe = false;
-
-        if (repr->attribute("inkscape:stockid")) {
-            GSList * markers_doc_ml = ink_marker_list_get(markers_doc);
-            for (; markers_doc_ml != NULL; markers_doc_ml = markers_doc_ml->next) {
-                const gchar* stockid = SP_OBJECT_REPR(markers_doc_ml->data)->attribute("inkscape:stockid");
-                if (stockid && !strcmp(repr->attribute("inkscape:stockid"), stockid))
-                    stock_dupe = true;
-            }
-        }
-
-        if (stock_dupe) // stock item, dont add to list from current doc
-            continue;
-*/
-
         // Add to the list of markers we really do wish to show
         clean_ml = g_slist_prepend (clean_ml, ml->data);
     }
@@ -766,12 +776,63 @@ gchar const *buffer = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:sodipodi=
     return sp_document_new_from_mem (buffer, strlen(buffer), FALSE);
 }
 
+static void
+ink_marker_menu_create_menu(GtkWidget *m, gchar const *menu_id, SPDocument *doc, SPDocument *sandbox)
+{
+    static SPDocument *markers_doc = NULL;
+
+    // add "None"
+    GtkWidget *i = gtk_menu_item_new();
+    gtk_widget_show(i);
+
+    g_object_set_data(G_OBJECT(i), "marker", (void *) "none");
+
+    GtkWidget *hb = gtk_hbox_new(FALSE,  MARKER_ITEM_MARGIN);
+    gtk_widget_show(hb);
+
+    GtkWidget *l = gtk_label_new( _("None") );
+    gtk_widget_show(l);
+    gtk_misc_set_alignment(GTK_MISC(l), 0.0, 0.5);
+
+    gtk_box_pack_start(GTK_BOX(hb), l, TRUE, TRUE, 0);
+
+    gtk_widget_show(hb);
+    gtk_container_add(GTK_CONTAINER(i), hb);
+    gtk_menu_append(GTK_MENU(m), i);
+
+    // find and load  markers.svg
+    if (markers_doc == NULL) {
+        char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
+        if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
+            markers_doc = sp_document_new(markers_source, FALSE);
+        }
+        g_free(markers_source);
+    }
+
+    // suck in from current doc
+    sp_marker_list_from_doc ( m, NULL, doc, markers_doc, sandbox, menu_id );
+
+    // add separator
+    {
+        GtkWidget *i = gtk_separator_menu_item_new();
+        gtk_widget_show(i);
+        gtk_menu_append(GTK_MENU(m), i);
+    }
+
+    // suck in from markers.svg
+    if (markers_doc) {
+        sp_document_ensure_up_to_date(doc);
+        sp_marker_list_from_doc ( m, doc, markers_doc, NULL, sandbox, menu_id );
+    }
+
+}
+
 
 /**
  * Creates a menu widget to display markers from markers.svg
  */
 static GtkWidget *
-ink_marker_menu( GtkWidget *tbl, gchar *menu_id, SPDocument *sandbox)
+ink_marker_menu( GtkWidget */*tbl*/, gchar const *menu_id, SPDocument *sandbox)
 {
     SPDesktop *desktop = inkscape_active_desktop();
     SPDocument *doc = sp_desktop_document(desktop);
@@ -790,56 +851,12 @@ ink_marker_menu( GtkWidget *tbl, gchar *menu_id, SPDocument *sandbox)
         gtk_widget_set_sensitive(mnu, FALSE);
 
     } else {
-
-        // add "None"
-        {
-            GtkWidget *i = gtk_menu_item_new();
-            gtk_widget_show(i);
-
-            g_object_set_data(G_OBJECT(i), "marker", (void *) "none");
-
-            GtkWidget *hb = gtk_hbox_new(FALSE,  MARKER_ITEM_MARGIN);
-            gtk_widget_show(hb);
-
-            GtkWidget *l = gtk_label_new( _("None") );
-            gtk_widget_show(l);
-            gtk_misc_set_alignment(GTK_MISC(l), 0.0, 0.5);
-
-            gtk_box_pack_start(GTK_BOX(hb), l, TRUE, TRUE, 0);
-
-            gtk_widget_show(hb);
-            gtk_container_add(GTK_CONTAINER(i), hb);
-            gtk_menu_append(GTK_MENU(m), i);
-        }
-
-        // find and load  markers.svg
-        static SPDocument *markers_doc = NULL;
-        char *markers_source = g_build_filename(INKSCAPE_MARKERSDIR, "markers.svg", NULL);
-        if (Inkscape::IO::file_test(markers_source, G_FILE_TEST_IS_REGULAR)) {
-            markers_doc = sp_document_new(markers_source, FALSE);
-        }
-        g_free(markers_source);
-
-        // suck in from current doc
-        sp_marker_list_from_doc ( m, NULL, doc, markers_doc, sandbox, menu_id );
-
-        // add separator
-        {
-            GtkWidget *i = gtk_separator_menu_item_new();
-            gtk_widget_show(i);
-            gtk_menu_append(GTK_MENU(m), i);
-        }
-
-        // suck in from markers.svg
-        if (markers_doc) {
-            sp_document_ensure_up_to_date(doc);
-            sp_marker_list_from_doc ( m, doc, markers_doc, NULL, sandbox, menu_id );
-        }
+        ink_marker_menu_create_menu(m, menu_id, doc, sandbox);
 
         gtk_widget_set_sensitive(mnu, TRUE);
     }
 
-    gtk_object_set_data(GTK_OBJECT(mnu), "menu_id", menu_id);
+    gtk_object_set_data(GTK_OBJECT(mnu), "menu_id", const_cast<gchar *>(menu_id));
     gtk_option_menu_set_menu(GTK_OPTION_MENU(mnu), m);
 
     /* Set history */
@@ -875,7 +892,7 @@ sp_marker_select(GtkOptionMenu *mnu, GtkWidget *spw)
     }
     gchar *markid = (gchar *) g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))),
                                                 "marker");
-    gchar *marker = "";
+    gchar const *marker = "";
     if (strcmp(markid, "none")){
        gchar *stockid = (gchar *) g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))),
                                                 "stockid");
@@ -892,12 +909,17 @@ sp_marker_select(GtkOptionMenu *mnu, GtkWidget *spw)
     }
 
     SPCSSAttr *css = sp_repr_css_attr_new();
-    gchar *menu_id = (gchar *) g_object_get_data(G_OBJECT(mnu), "menu_id");
+    gchar const *menu_id = (gchar const *) g_object_get_data(G_OBJECT(mnu), "menu_id");
     sp_repr_css_set_property(css, menu_id, marker);
 
-     Inkscape::Selection *selection = sp_desktop_selection(desktop);
-     GSList const *items = selection->itemList();
-     for (; items != NULL; items = items->next) {
+    // Also update the marker dropdown menus, so the document's markers
+    // show up at the top of the menu
+//    sp_stroke_style_line_update( SP_WIDGET(spw), desktop ? sp_desktop_selection(desktop) : NULL);
+    ink_markers_menu_update(SP_WIDGET(spw));
+
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
+    GSList const *items = selection->itemList();
+    for (; items != NULL; items = items->next) {
          SPItem *item = (SPItem *) items->data;
          if (!SP_IS_SHAPE(item) || SP_IS_RECT(item)) // can't set marker to rect, until it's converted to using <path>
              continue;
@@ -911,8 +933,69 @@ sp_marker_select(GtkOptionMenu *mnu, GtkWidget *spw)
 
     sp_repr_css_attr_unref(css);
 
-    sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, 
+    sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
                      _("Set markers"));
+
+};
+
+static int
+ink_marker_menu_get_pos(GtkMenu *mnu, gchar const *markname)
+{
+    if (markname == NULL)
+        markname = (gchar const *) g_object_get_data(G_OBJECT(gtk_menu_get_active(mnu)), "marker");
+
+    if (markname == NULL)
+        return 0;
+
+    GList const *kids = GTK_MENU_SHELL(mnu)->children;
+    int i = 0;
+    for (; kids != NULL; kids = kids->next) {
+        gchar const *mark = (gchar const *) g_object_get_data(G_OBJECT(kids->data), "marker");
+        if ( mark && strcmp(mark, markname) == 0 ) {
+            break;
+        }
+        i++;
+    }
+    return i;
+}
+
+static void
+ink_markers_menu_update(SPWidget* spw) {
+    SPDesktop  *desktop = inkscape_active_desktop();
+    SPDocument *document = sp_desktop_document(desktop);
+    SPDocument *sandbox = ink_markers_preview_doc ();
+    GtkWidget  *m;
+    int        pos;
+
+    gtk_signal_handler_block_by_func( GTK_OBJECT(marker_start_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
+    pos = ink_marker_menu_get_pos(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(marker_start_menu))), NULL);
+    m = gtk_menu_new();
+    gtk_widget_show(m);
+    ink_marker_menu_create_menu(m, "marker-start", document, sandbox);
+    gtk_option_menu_remove_menu(GTK_OPTION_MENU(marker_start_menu));
+    gtk_option_menu_set_menu(GTK_OPTION_MENU(marker_start_menu), m);
+    gtk_option_menu_set_history(GTK_OPTION_MENU(marker_start_menu), pos);
+    gtk_signal_handler_unblock_by_func( GTK_OBJECT(marker_start_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
+
+    gtk_signal_handler_block_by_func( GTK_OBJECT(marker_mid_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
+    pos = ink_marker_menu_get_pos(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(marker_mid_menu))), NULL);
+    m = gtk_menu_new();
+    gtk_widget_show(m);
+    ink_marker_menu_create_menu(m, "marker-mid", document, sandbox);
+    gtk_option_menu_remove_menu(GTK_OPTION_MENU(marker_mid_menu));
+    gtk_option_menu_set_menu(GTK_OPTION_MENU(marker_mid_menu), m);
+    gtk_option_menu_set_history(GTK_OPTION_MENU(marker_mid_menu), pos);
+    gtk_signal_handler_unblock_by_func( GTK_OBJECT(marker_mid_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
+
+    gtk_signal_handler_block_by_func( GTK_OBJECT(marker_end_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
+    pos = ink_marker_menu_get_pos(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(marker_end_menu))), NULL);
+    m = gtk_menu_new();
+    gtk_widget_show(m);
+    ink_marker_menu_create_menu(m, "marker-end", document, sandbox);
+    gtk_option_menu_remove_menu(GTK_OPTION_MENU(marker_end_menu));
+    gtk_option_menu_set_menu(GTK_OPTION_MENU(marker_end_menu), m);
+    gtk_option_menu_set_history(GTK_OPTION_MENU(marker_end_menu), pos);
+    gtk_signal_handler_unblock_by_func( GTK_OBJECT(marker_end_menu), GTK_SIGNAL_FUNC(sp_marker_select), spw);
 }
 
 /**
@@ -1154,35 +1237,33 @@ sp_stroke_style_line_widget_new(void)
     // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes
     // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path.
     spw_label(t, _("Start Markers:"), 0, i);
-    GtkWidget *mnu  = ink_marker_menu( spw ,"marker-start", sandbox);
-    gtk_signal_connect( GTK_OBJECT(mnu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
-    gtk_widget_show(mnu);
-    gtk_table_attach( GTK_TABLE(t), mnu, 1, 4, i, i+1,
+    marker_start_menu  = ink_marker_menu( spw ,"marker-start", sandbox);
+    gtk_signal_connect( GTK_OBJECT(marker_start_menu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
+    gtk_widget_show(marker_start_menu);
+    gtk_table_attach( GTK_TABLE(t), marker_start_menu, 1, 4, i, i+1,
                       (GtkAttachOptions)( GTK_EXPAND | GTK_FILL ),
                       (GtkAttachOptions)0, 0, 0 );
-    gtk_object_set_data(GTK_OBJECT(spw), "start_mark_menu", mnu);
+    gtk_object_set_data(GTK_OBJECT(spw), "start_mark_menu", marker_start_menu);
 
     i++;
     spw_label(t, _("Mid Markers:"), 0, i);
-    mnu = NULL;
-    mnu  = ink_marker_menu( spw ,"marker-mid", sandbox);
-    gtk_signal_connect( GTK_OBJECT(mnu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
-    gtk_widget_show(mnu);
-    gtk_table_attach( GTK_TABLE(t), mnu, 1, 4, i, i+1,
+    marker_mid_menu = ink_marker_menu( spw ,"marker-mid", sandbox);
+    gtk_signal_connect( GTK_OBJECT(marker_mid_menu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
+    gtk_widget_show(marker_mid_menu);
+    gtk_table_attach( GTK_TABLE(t), marker_mid_menu, 1, 4, i, i+1,
                       (GtkAttachOptions)( GTK_EXPAND | GTK_FILL ),
                       (GtkAttachOptions)0, 0, 0 );
-    gtk_object_set_data(GTK_OBJECT(spw), "mid_mark_menu", mnu);
+    gtk_object_set_data(GTK_OBJECT(spw), "mid_mark_menu", marker_mid_menu);
 
     i++;
     spw_label(t, _("End Markers:"), 0, i);
-    mnu = NULL;
-    mnu  = ink_marker_menu( spw ,"marker-end", sandbox);
-    gtk_signal_connect( GTK_OBJECT(mnu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
-    gtk_widget_show(mnu);
-    gtk_table_attach( GTK_TABLE(t), mnu, 1, 4, i, i+1,
+    marker_end_menu = ink_marker_menu( spw ,"marker-end", sandbox);
+    gtk_signal_connect( GTK_OBJECT(marker_end_menu), "changed", GTK_SIGNAL_FUNC(sp_marker_select), spw );
+    gtk_widget_show(marker_end_menu);
+    gtk_table_attach( GTK_TABLE(t), marker_end_menu, 1, 4, i, i+1,
                       (GtkAttachOptions)( GTK_EXPAND | GTK_FILL ),
                       (GtkAttachOptions)0, 0, 0 );
-    gtk_object_set_data(GTK_OBJECT(spw), "end_mark_menu", mnu);
+    gtk_object_set_data(GTK_OBJECT(spw), "end_mark_menu", marker_end_menu);
 
     i++;
 
@@ -1207,9 +1288,8 @@ sp_stroke_style_line_widget_new(void)
  * the stroke line style to be updated.
  */
 static void
-sp_stroke_style_line_construct(SPWidget *spw, gpointer data)
+sp_stroke_style_line_construct(SPWidget *spw, gpointer /*data*/)
 {
-
 #ifdef SP_SS_VERBOSE
     g_print( "Stroke style widget constructed: inkscape %p repr %p\n",
              spw->inkscape, spw->repr );
@@ -1219,18 +1299,18 @@ sp_stroke_style_line_construct(SPWidget *spw, gpointer data)
                                     ( SP_ACTIVE_DESKTOP
                                       ? sp_desktop_selection(SP_ACTIVE_DESKTOP)
                                       : NULL ));
-    } 
+    }
 }
 
 /**
- * Callback for when stroke style widget is modified.  
+ * Callback for when stroke style widget is modified.
  * Triggers update action.
  */
 static void
-sp_stroke_style_line_selection_modified ( SPWidget *spw,
-                                       Inkscape::Selection *selection,
-                                       guint flags,
-                                       gpointer data )
+sp_stroke_style_line_selection_modified( SPWidget *spw,
+                                         Inkscape::Selection *selection,
+                                         guint flags,
+                                         gpointer /*data*/ )
 {
     if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
         sp_stroke_style_line_update (spw, selection);
@@ -1243,9 +1323,9 @@ sp_stroke_style_line_selection_modified ( SPWidget *spw,
  * Triggers update action.
  */
 static void
-sp_stroke_style_line_selection_changed ( SPWidget *spw,
-                                       Inkscape::Selection *selection,
-                                       gpointer data )
+sp_stroke_style_line_selection_changed( SPWidget *spw,
+                                        Inkscape::Selection *selection,
+                                        gpointer /*data*/ )
 {
     sp_stroke_style_line_update (spw, selection);
 }
@@ -1341,12 +1421,12 @@ sp_stroke_style_line_update(SPWidget *spw, Inkscape::Selection *sel)
     GtkWidget *dsel = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(spw), "dash"));
 
     // create temporary style
-    SPStyle *query = sp_style_new ();
+    SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
     // query into it
-    int result_sw = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEWIDTH); 
-    int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT); 
-    int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP); 
-    int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN); 
+    int result_sw = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEWIDTH);
+    int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT);
+    int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKECAP);
+    int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_STROKEJOIN);
 
     if (result_sw == QUERY_STYLE_NOTHING) {
         /* No objects stroked, set insensitive */
@@ -1393,7 +1473,7 @@ sp_stroke_style_line_update(SPWidget *spw, Inkscape::Selection *sel)
         sp_stroke_style_set_cap_buttons(spw, NULL);
     }
 
-    g_free (query);
+    sp_style_unref(query);
 
     if (!sel || sel->isEmpty())
         return;
@@ -1521,7 +1601,7 @@ sp_stroke_style_scale_line(SPWidget *spw)
 
     sp_repr_css_attr_unref(css);
 
-    sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE, 
+    sp_document_done(document, SP_VERB_DIALOG_FILL_STROKE,
                      _("Set stroke style"));
 
     gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE));
@@ -1529,11 +1609,11 @@ sp_stroke_style_scale_line(SPWidget *spw)
 
 
 /**
- * Callback for when the stroke style's width changes.  
+ * Callback for when the stroke style's width changes.
  * Causes all line styles to be applied to all selected items.
  */
 static void
-sp_stroke_style_width_changed(GtkAdjustment *adj, SPWidget *spw)
+sp_stroke_style_width_changed(GtkAdjustment */*adj*/, SPWidget *spw)
 {
     if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
         return;
@@ -1543,11 +1623,11 @@ sp_stroke_style_width_changed(GtkAdjustment *adj, SPWidget *spw)
 }
 
 /**
- * Callback for when the stroke style's miterlimit changes.  
+ * Callback for when the stroke style's miterlimit changes.
  * Causes all line styles to be applied to all selected items.
  */
 static void
-sp_stroke_style_miterlimit_changed(GtkAdjustment *adj, SPWidget *spw)
+sp_stroke_style_miterlimit_changed(GtkAdjustment */*adj*/, SPWidget *spw)
 {
     if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
         return;
@@ -1557,11 +1637,11 @@ sp_stroke_style_miterlimit_changed(GtkAdjustment *adj, SPWidget *spw)
 }
 
 /**
- * Callback for when the stroke style's dash changes.  
+ * Callback for when the stroke style's dash changes.
  * Causes all line styles to be applied to all selected items.
  */
 static void
-sp_stroke_style_line_dash_changed(SPDashSelector *dsel, SPWidget *spw)
+sp_stroke_style_line_dash_changed(SPDashSelector */*dsel*/, SPWidget *spw)
 {
     if (gtk_object_get_data(GTK_OBJECT(spw), "update")) {
         return;
@@ -1689,19 +1769,7 @@ ink_marker_menu_set_current(SPObject *marker, GtkOptionMenu *mnu)
         else
             markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("id"));
 
-        int markpos = 0;
-        GList *kids = GTK_MENU_SHELL(m)->children;
-        int i = 0;
-        for (; kids != NULL; kids = kids->next) {
-            gchar *mark = (gchar *) g_object_get_data(G_OBJECT(kids->data), "marker");
-            if ( mark && strcmp(mark, markname) == 0 ) {
-                if ( mark_is_stock && !strcmp((gchar *) g_object_get_data(G_OBJECT(kids->data), "stockid"), "true"))
-                    markpos = i;
-                if ( !mark_is_stock && !strcmp((gchar *) g_object_get_data(G_OBJECT(kids->data), "stockid"), "false"))
-                    markpos = i;
-            }
-            i++;
-        }
+        int markpos = ink_marker_menu_get_pos(m, markname);
         gtk_option_menu_set_history(GTK_OPTION_MENU(mnu), markpos);
 
         g_free (markname);
@@ -1713,7 +1781,7 @@ ink_marker_menu_set_current(SPObject *marker, GtkOptionMenu *mnu)
 }
 
 /**
- * Updates the marker menus to highlight the appropriate marker and scroll to 
+ * Updates the marker menus to highlight the appropriate marker and scroll to
  * that marker.
  */
 static void
@@ -1804,7 +1872,6 @@ ink_extract_marker_name(gchar const *n)
     gchar* b = g_strdup(p);
     b[c] = '\0';
 
-
     SPDesktop *desktop = inkscape_active_desktop();
     SPDocument *doc = sp_desktop_document(desktop);
     SPObject *marker = doc->getObjectById(b);