From 32461c0cc717f51ba84908e1eea5b1ee150cf27e Mon Sep 17 00:00:00 2001 From: cilix42 Date: Fri, 11 Jan 2008 19:01:50 +0000 Subject: [PATCH] Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase. --- src/box3d-context.cpp | 9 ++++++++ src/box3d.cpp | 43 +++++++++++++++++++++++++++++++++++++ src/box3d.h | 2 ++ src/menus-skeleton.h | 1 + src/rect-context.cpp | 9 ++++++++ src/select-context.cpp | 7 ++++++ src/selection-chemistry.cpp | 35 ++++++++++++++++++++++++++++++ src/selection-chemistry.h | 1 + src/sp-guide.cpp | 27 +++++++++++++++++++++++ src/sp-guide.h | 3 +++ src/sp-rect.cpp | 27 +++++++++++++++++++++++ src/sp-rect.h | 2 ++ src/verbs.cpp | 6 ++++++ src/verbs.h | 1 + 14 files changed, 173 insertions(+) diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index 68480a00d..bbc8097f5 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -24,6 +24,7 @@ #include "document.h" #include "sp-namedview.h" #include "selection.h" +#include "selection-chemistry.h" #include "desktop-handles.h" #include "snap.h" #include "display/curve.h" @@ -532,6 +533,14 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven ret = true; break; + case GDK_g: + case GDK_G: + if (MOD__SHIFT_ONLY) { + sp_selection_to_guides(); + ret = true; + } + break; + case GDK_P: { if (MOD__SHIFT && MOD__CTRL) break; // Don't catch Shift+Ctrl+P (Preferences dialog) diff --git a/src/box3d.cpp b/src/box3d.cpp index 082c83bbd..631d5cfc1 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -32,6 +32,8 @@ #include "persp3d-reference.h" #include "uri.h" #include "2geom/geom.h" +#include "sp-guide.h" +#include "sp-namedview.h" #include "desktop.h" #include "macros.h" @@ -1486,6 +1488,47 @@ box3d_convert_to_group(SPBox3D *box) { return SP_GROUP(doc->getObjectByRepr(grepr)); } +static void +box3d_push_back_corner_pair(SPBox3D *box, std::list > &pts, int c1, int c2) { + pts.push_back(std::make_pair(box3d_get_corner_screen(box, c1).to_2geom(), + box3d_get_corner_screen(box, c2).to_2geom())); +} + +void +box3d_convert_to_guides(SPBox3D *box, bool write_undo) { + SPDocument *doc = SP_OBJECT_DOCUMENT(box); + //SPDesktop *desktop = inkscape_active_desktop(); + //Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + + std::list > pts; + + /* perspective lines in X direction */ + box3d_push_back_corner_pair(box, pts, 0, 1); + box3d_push_back_corner_pair(box, pts, 2, 3); + box3d_push_back_corner_pair(box, pts, 4, 5); + box3d_push_back_corner_pair(box, pts, 6, 7); + + /* perspective lines in Y direction */ + box3d_push_back_corner_pair(box, pts, 0, 2); + box3d_push_back_corner_pair(box, pts, 1, 3); + box3d_push_back_corner_pair(box, pts, 4, 6); + box3d_push_back_corner_pair(box, pts, 5, 7); + + /* perspective lines in Z direction */ + box3d_push_back_corner_pair(box, pts, 0, 4); + box3d_push_back_corner_pair(box, pts, 1, 5); + box3d_push_back_corner_pair(box, pts, 2, 6); + box3d_push_back_corner_pair(box, pts, 3, 7); + + sp_guide_pt_pairs_to_guides(doc, pts); + + SP_OBJECT(box)->deleteObject(true); + + if (write_undo) { + sp_document_done(doc, SP_VERB_CONTEXT_3DBOX, _("Convert to guides")); + } +} + /* Local Variables: mode:c++ diff --git a/src/box3d.h b/src/box3d.h index 12d6bfc4b..bcbd975c5 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -82,6 +82,8 @@ Persp3D *box3d_get_perspective(SPBox3D const *box); void box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp, bool recompute_corners = false); SPGroup *box3d_convert_to_group(SPBox3D *box); +void box3d_convert_to_guides(SPBox3D *box, bool write_undo = true); + #endif /* __SP_BOX3D_H__ */ diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index bdbbc51de..b96ee2302 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -171,6 +171,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" diff --git a/src/rect-context.cpp b/src/rect-context.cpp index 5969c1fb2..938b4496d 100644 --- a/src/rect-context.cpp +++ b/src/rect-context.cpp @@ -25,6 +25,7 @@ #include "document.h" #include "sp-namedview.h" #include "selection.h" +#include "selection-chemistry.h" #include "desktop-handles.h" #include "snap.h" #include "desktop.h" @@ -413,6 +414,14 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent } break; + case GDK_g: + case GDK_G: + if (MOD__SHIFT_ONLY) { + sp_selection_to_guides(); + ret = true; + } + break; + case GDK_Escape: sp_desktop_selection(desktop)->clear(); //TODO: make dragging escapable by Esc diff --git a/src/select-context.cpp b/src/select-context.cpp index cdf63785c..48afadb2b 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -888,6 +888,13 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) ret = TRUE; } break; + case GDK_g: + case GDK_G: + if (MOD__SHIFT_ONLY) { + sp_selection_to_guides(); + ret = true; + } + break; default: break; } diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 56ef7b01f..fc2a6a271 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -72,12 +72,14 @@ #include #include "helper/units.h" #include "sp-item.h" +#include "box3d.h" #include "unit-constants.h" #include "xml/simple-document.h" #include "sp-filter-reference.h" #include "gradient-drag.h" #include "uri-references.h" #include "live_effects/lpeobject.h" +#include "sp-rect.h" using NR::X; using NR::Y; @@ -2440,6 +2442,39 @@ void sp_selection_to_marker(bool apply) _("Objects to marker")); } +void sp_selection_to_guides() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop == NULL) + return; + + SPDocument *doc = sp_desktop_document(desktop); + Inkscape::Selection *selection = sp_desktop_selection(desktop); + // we need to copy the list because it gets reset when objects are deleted + GSList *items = g_slist_copy((GSList *) selection->itemList()); + + bool performed = false; + for (GSList const *i = items; i != NULL; i = i->next) { + if (SP_IS_RECT(i->data)) { + sp_rect_convert_to_guides(SP_RECT(i->data), false); + performed = true; + } else if (SP_IS_BOX3D(i->data)) { + box3d_convert_to_guides(SP_BOX3D(i->data), false); + performed = true; + } + } + + if (!performed) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to convert to guides (selection must contain at least one rectangle or 3D box).")); + return; + } + + if (performed) { + sp_document_done (doc, SP_VERB_EDIT_SELECTION_2_GUIDES, + _("Objects to guides")); + } +} + void sp_selection_tile(bool apply) { diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 09f957332..0dc1da7e7 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -36,6 +36,7 @@ void sp_selection_unlink(); void sp_select_clone_original (); void sp_selection_to_marker(bool apply = true); +void sp_selection_to_guides(); void sp_selection_tile(bool apply = true); void sp_selection_untile(); diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index 26d60601c..68e322178 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -34,6 +34,7 @@ #include "desktop.h" #include "sp-namedview.h" #include <2geom/angle.h> +#include "document.h" using std::vector; @@ -235,6 +236,32 @@ static void sp_guide_set(SPObject *object, unsigned int key, const gchar *value) } } +SPGuide * +sp_guide_create(SPDocument *doc, Geom::Point const &pt1, Geom::Point const &pt2) { + SPDesktop *desktop = inkscape_active_desktop(); + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + + Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide"); + + Geom::Point n = Geom::rot90(pt2 - pt1); + + sp_repr_set_point(repr, "position", pt1); + sp_repr_set_point(repr, "orientation", n); + + SP_OBJECT_REPR(desktop->namedview)->appendChild(repr); + Inkscape::GC::release(repr); + + SPGuide *guide= SP_GUIDE(doc->getObjectByRepr(repr)); + return guide; +} + +void +sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list > &pts) { + for (std::list >::iterator i = pts.begin(); i != pts.end(); ++i) { + sp_guide_create(doc, (*i).first, (*i).second); + } +} + void sp_guide_show(SPGuide *guide, SPCanvasGroup *group, GCallback handler) { SPCanvasItem *item = sp_guideline_new(group, guide->point_on_line, guide->normal_to_line.to_2geom()); diff --git a/src/sp-guide.h b/src/sp-guide.h index dbbebadb7..a9b04dfaa 100644 --- a/src/sp-guide.h +++ b/src/sp-guide.h @@ -45,6 +45,9 @@ struct SPGuideClass { GType sp_guide_get_type(); +SPGuide *sp_guide_create(SPDesktop *desktop, Geom::Point const &pt1, Geom::Point const &pt2); +void sp_guide_pt_pairs_to_guides(SPDocument *doc, std::list > &pts); + void sp_guide_show(SPGuide *guide, SPCanvasGroup *group, GCallback handler); void sp_guide_hide(SPGuide *guide, SPCanvas *canvas); void sp_guide_sensitize(SPGuide *guide, SPCanvas *canvas, gboolean sensitive); diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp index d9caebd5a..e8e04cc51 100644 --- a/src/sp-rect.cpp +++ b/src/sp-rect.cpp @@ -28,6 +28,7 @@ #include "sp-rect.h" #include #include "xml/repr.h" +#include "sp-guide.h" #define noRECT_VERBOSE @@ -578,6 +579,32 @@ static void sp_rect_snappoints(SPItem const *item, SnapPointsIter p) *p = NR::Point(rect->x.computed + rect->width.computed, rect->y.computed) * i2d; } +void +sp_rect_convert_to_guides(SPRect *rect, bool write_undo) { + SPDocument *doc = SP_OBJECT_DOCUMENT(rect); + std::list > pts; + + NR::Matrix const i2d (sp_item_i2d_affine(SP_ITEM(rect))); + + NR::Point A1(NR::Point(rect->x.computed, rect->y.computed) * i2d); + NR::Point A2(NR::Point(rect->x.computed, rect->y.computed + rect->height.computed) * i2d); + NR::Point A3(NR::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed) * i2d); + NR::Point A4(NR::Point(rect->x.computed + rect->width.computed, rect->y.computed) * i2d); + + pts.push_back(std::make_pair(A1.to_2geom(), A2.to_2geom())); + pts.push_back(std::make_pair(A2.to_2geom(), A3.to_2geom())); + pts.push_back(std::make_pair(A3.to_2geom(), A4.to_2geom())); + pts.push_back(std::make_pair(A4.to_2geom(), A1.to_2geom())); + + sp_guide_pt_pairs_to_guides(doc, pts); + + SP_OBJECT(rect)->deleteObject(true); + + if (write_undo) { + sp_document_done(doc, SP_VERB_CONTEXT_RECT, _("Convert to guides")); + } +} + /* Local Variables: mode:c++ diff --git a/src/sp-rect.h b/src/sp-rect.h index 4cf3b24ba..0133922e8 100644 --- a/src/sp-rect.h +++ b/src/sp-rect.h @@ -62,4 +62,6 @@ gdouble sp_rect_get_visible_height (SPRect *rect); void sp_rect_compensate_rxry (SPRect *rect, NR::Matrix xform); +void sp_rect_convert_to_guides(SPRect *rect, bool write_undo = true); + #endif diff --git a/src/verbs.cpp b/src/verbs.cpp index 53650a262..736ddc3d5 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -888,6 +888,9 @@ EditVerb::perform(SPAction *action, void *data, void */*pdata*/) case SP_VERB_EDIT_SELECTION_2_MARKER: sp_selection_to_marker(); break; + case SP_VERB_EDIT_SELECTION_2_GUIDES: + sp_selection_to_guides(); + break; case SP_VERB_EDIT_TILE: sp_selection_tile(); break; @@ -2191,6 +2194,9 @@ Verb *Verb::_base_verbs[] = { // TRANSLATORS: Convert selection to a line marker new EditVerb(SP_VERB_EDIT_SELECTION_2_MARKER, "ObjectsToMarker", N_("Objects to _Marker"), N_("Convert selection to a line marker"), NULL), + // TRANSLATORS: Convert selection to a collection of guidelines + new EditVerb(SP_VERB_EDIT_SELECTION_2_GUIDES, "ObjectsToGuides", N_("Objects to Gu_ides"), + N_("Convert selected objects to a collection of guidelines aligned with their edges"), NULL), // TRANSLATORS: Convert selection to a rectangle with tiled pattern fill new EditVerb(SP_VERB_EDIT_TILE, "ObjectsToPattern", N_("Objects to Patter_n"), N_("Convert selection to a rectangle with tiled pattern fill"), NULL), diff --git a/src/verbs.h b/src/verbs.h index 9f5cbe3c8..104d4db0d 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -67,6 +67,7 @@ enum { SP_VERB_EDIT_UNLINK_CLONE, SP_VERB_EDIT_CLONE_SELECT_ORIGINAL, SP_VERB_EDIT_SELECTION_2_MARKER, + SP_VERB_EDIT_SELECTION_2_GUIDES, SP_VERB_EDIT_TILE, SP_VERB_EDIT_UNTILE, SP_VERB_EDIT_CLEAR_ALL, -- 2.30.2