From 507d4f62916fd9652363c2490d6e896699fda9ed Mon Sep 17 00:00:00 2001 From: bryce Date: Thu, 7 Dec 2006 04:41:04 +0000 Subject: [PATCH] Marker menus now display custom markers in a document that are present when the document is loaded. The menus won't update with new markers, though, and there's a couple other issues that need to be addressed before its 100% reliable. --- doc/markers_design.txt | 98 +++++++++++++++++++++++++++++ src/dialogs/stroke-style.cpp | 119 +++++++++++++++++++++-------------- src/marker.cpp | 4 +- 3 files changed, 174 insertions(+), 47 deletions(-) create mode 100644 doc/markers_design.txt diff --git a/doc/markers_design.txt b/doc/markers_design.txt new file mode 100644 index 000000000..f41eaa8e4 --- /dev/null +++ b/doc/markers_design.txt @@ -0,0 +1,98 @@ + Markers Design + Bryce W. Harrington + ----------- + +Markers (or "arrowheads") are drawing elements specified by the SVG +standard that can be placed on lines at one of three positions: Start, +End, or Midpoints. This document isn't intended to be an exhaustive +guide to Markers, but rather to simply capture notes about the +implementation of them within Inkscape. + +History +======= +The marker code was originally developed by Lauris for Sodipodi, but due +to various issues, the code was not hooked to the interface. Thus +there was no way for users to actually put markers on lines. + +Early in Inkscape, I dug through the code and reactivated the markers +function, and then hammered on a few of the main issues to get markers +to (mostly) work. There were a variety of remaining issues (e.g., you +couldn't change marker colors, updates didn't work very well, and snap +points were messed up.) But at least they no longer crashed when you +used them. ;-) + +Simarilius and others did the work of getting the UI hooked up for +markers, and other assorted fixes. A set of stock markers were created +and distributed with Inkscape. + +Since then, though, the code has sat mostly idle, as no one has had +time/inclination to put more work on it. Despite this, the remaining +marker issues (color setting in particular) remain popular requests +among users. + +I'm hoping this document assists anyone wishing to work on markers to +come up to speed with the code more easily than otherwise. + +Implementation Files +==================== +The following files contain code of relevance to markers: + +marker.h: tbd + +marker.cpp: Implements the sp_marker class, providing functionality for + managing the relationship of markers to lines or other objects they've + been applied to. Updates reprs and properties as the marker's + definition changes. Handles updates/changes to marker views as well. + +sp-shape.cpp: tbd + +selection-chemistry.cpp: tbd + +sp-marker-loc.h: tbd + +display/nr-arena-shape.cpp: tbd + +stock-items.cpp: tbd + +dialogs/stroke-style.h: tbd + +dialogs/stroke-style.cpp: Implements the stroke style dialog, which +includes the widgets for displaying stock markers that can be applied to +lines. + + +Marker Architecture +=================== +A marker is a distinct drawing element that exists in the section +of an SVG document. Markers often appear multiple places in a document +- for instance, you might have a diagram with dozens of lines, each +tipped by a copy of the same arrow. Rather than paste a copy of the +arrowhead in at each point it's used, a single definition is made, and a +reference, or 'href', is attached at each place its used. + +In Inkscape, the marker definition is implemented as a 'SPMarker' +object, and each reference is a 'SPMarkerView' object. Each SPMarker +has a listing of all its SPMarkerViews, which it can use for update +purposes when it changes. + + + +Stroke Dialog +============= +In the stroke style dialog, several routines allow for setting and +interacting with the stroke markers. Most of these routines are already +documented, but a few are worth some additional attention. + +sp_marker_prev_new(): Generates the preview images of markers for +display in the marker menu. + +sp_marker_list_from_doc(): Generates a listing of non-stock markers in +the document. Generates preview and label for the marker. + +ink_markers_preview_doc(): Returns a new document containing default +start, mid, and end markers by creating the SVG text and running it +through sp_document_new_from_mem. I'm not entirely sure why this +exists, but it's called from sp_stroke_style_line_widget_new() so +presumably is needed. + +ink_marker_menu(): Generates the marker menu. diff --git a/src/dialogs/stroke-style.cpp b/src/dialogs/stroke-style.cpp index 5e3319ffc..152569a5a 100644 --- a/src/dialogs/stroke-style.cpp +++ b/src/dialogs/stroke-style.cpp @@ -5,7 +5,7 @@ * * Authors: * Lauris Kaplinski - * Bryce Harrington + * Bryce Harrington * bulia byak * * Copyright (C) 2001-2005 authors @@ -546,7 +546,8 @@ sp_stroke_radio_button(GtkWidget *tb, char const *icon, /** * Creates a copy of the marker named mname, determines its visible and renderable - * area in menu_id's bounding box, and then renders it. + * area in menu_id's bounding box, and then renders it. This allows us to fill in + * preview images of each marker in the marker menu. */ static GtkWidget * sp_marker_prev_new(unsigned size, gchar const *mname, @@ -657,62 +658,44 @@ sp_marker_prev_new(unsigned size, gchar const *mname, } -#define MARKER_ITEM_MARGIN 0 - - /** - * sp_marker_list_from_doc() - * - * \brief Pick up all markers from source, except those that are in - * current_doc (if non-NULL), and add items to the m menu - * + * Returns a list of markers in the defs of the given source document as a GSList object + * Returns NULL if there are no markers in the document. */ -static void -sp_marker_list_from_doc (GtkWidget *m, SPDocument *current_doc, SPDocument *source, SPDocument *markers_doc, SPDocument *sandbox, gchar *menu_id) +GSList * +ink_marker_list_get (SPDocument *source) { + if (source == NULL) + return NULL; - // search through defs - GSList *ml = NULL; - SPDefs *defs= (SPDefs *) SP_DOCUMENT_DEFS (source); - for ( SPObject *ochild = sp_object_first_child(SP_OBJECT(defs)) ; ochild != NULL ; ochild = SP_OBJECT_NEXT (ochild) ) { - if (SP_IS_MARKER(ochild)) { - ml = g_slist_prepend (ml, ochild); + GSList *ml = NULL; + SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS (source); + for ( SPObject *child = sp_object_first_child(SP_OBJECT(defs)); + child != NULL; + child = SP_OBJECT_NEXT (child) ) + { + if (SP_IS_MARKER(child)) { + ml = g_slist_prepend (ml, child); } } + return ml; +} +#define MARKER_ITEM_MARGIN 0 + +/** + * 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) +{ // 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; - - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) ml->data); - - bool stock_dupe = false; - - if (markers_doc && repr->attribute("inkscape:stockid")) { - // find out if markers_doc has a marker with the same stockid, and if so, skip this - for (SPObject *child = sp_object_first_child(SP_OBJECT(SP_DOCUMENT_DEFS(markers_doc))) ; - child != NULL; - child = SP_OBJECT_NEXT(child) ) - { - if (SP_IS_MARKER(child) && - SP_OBJECT_REPR(child)->attribute("inkscape:stockid") && - !strcmp(repr->attribute("inkscape:stockid"), SP_OBJECT_REPR(child)->attribute("inkscape:stockid"))) { - stock_dupe = true; - } - } - } - - if (stock_dupe) // stock item, dont add to list from current doc - continue; - + for (; marker_list != NULL; marker_list = marker_list->next) { + Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) marker_list->data); GtkWidget *i = gtk_menu_item_new(); gtk_widget_show(i); @@ -744,8 +727,52 @@ sp_marker_list_from_doc (GtkWidget *m, SPDocument *current_doc, SPDocument *sour gtk_menu_append(GTK_MENU(m), i); } +} + +/** + * sp_marker_list_from_doc() + * + * \brief Pick up all markers from source, except those that are in + * current_doc (if non-NULL), and add items to the m menu + * + */ +static void +sp_marker_list_from_doc (GtkWidget *m, SPDocument *current_doc, SPDocument *source, SPDocument *markers_doc, SPDocument *sandbox, gchar *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; + + Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) ml->data); + bool stock_dupe = false; + + 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); + } + sp_marker_menu_build (m, clean_ml, source, sandbox, menu_id); g_slist_free (ml); + g_slist_free (clean_ml); } diff --git a/src/marker.cpp b/src/marker.cpp index 68b630920..65ed3789f 100644 --- a/src/marker.cpp +++ b/src/marker.cpp @@ -1,12 +1,14 @@ -#define __SP_MARKER_C__ +#define __MARKER_C__ /* * SVG implementation * * Authors: * Lauris Kaplinski + * Bryce Harrington * * Copyright (C) 1999-2003 Lauris Kaplinski + * 2004-2006 Bryce Harrington * * Released under GNU GPL, read the file 'COPYING' for more information */ -- 2.30.2