From: cilix42 Date: Mon, 18 Aug 2008 17:41:57 +0000 (+0000) Subject: Option to display measuring info in geometry tool X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=469edb969f8070f518f2100039d56ad53dd38594;p=inkscape.git Option to display measuring info in geometry tool --- diff --git a/src/lpe-tool-context.cpp b/src/lpe-tool-context.cpp index 44c81057c..ed243c1b2 100644 --- a/src/lpe-tool-context.cpp +++ b/src/lpe-tool-context.cpp @@ -17,6 +17,11 @@ #include "config.h" #endif +#include <2geom/sbasis-geometric.h> +#include +//#include + +#include "macros.h" #include "forward.h" #include "pixmaps/cursor-node.xpm" #include "pixmaps/cursor-crosshairs.xpm" @@ -31,6 +36,8 @@ #include "display/curve.h" #include "display/canvas-bpath.h" #include "message-stack.h" +#include "sp-path.h" +#include "helper/units.h" #include "lpe-tool-context.h" @@ -103,6 +110,7 @@ sp_lpetool_context_init(SPLPEToolContext *lc) lc->hot_y = 7; lc->canvas_bbox = NULL; + lc->measuring_items = new std::map; new (&lc->sel_changed_connection) sigc::connection(); } @@ -118,6 +126,10 @@ sp_lpetool_context_dispose(GObject *object) lc->canvas_bbox = NULL; } + lpetool_delete_measuring_items(lc); + delete lc->measuring_items; + lc->measuring_items = NULL; + lc->sel_changed_connection.disconnect(); lc->sel_changed_connection.~connection(); @@ -143,6 +155,7 @@ sp_lpetool_context_setup(SPEventContext *ec) lpetool_context_switch_mode(lc, Inkscape::LivePathEffect::INVALID_LPE); lpetool_context_reset_limiting_bbox(lc); + lpetool_create_measuring_items(lc); // TODO temp force: ec->enableSelectionCue(); @@ -230,8 +243,7 @@ sp_lpetool_context_root_handler(SPEventContext *event_context, GdkEvent *event) int mode = prefs_get_int_attribute("tools.lpetool", "mode", 0); EffectType type = lpesubtools[mode]; - // save drag origin - bool over_stroke = lc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), true); + //bool over_stroke = lc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), true); sp_pen_context_wait_for_LPE_mouse_clicks(lc, type, Inkscape::LivePathEffect::Effect::acceptsNumClicks(type)); @@ -408,6 +420,109 @@ lpetool_context_reset_limiting_bbox(SPLPEToolContext *lc) sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(lc->canvas_bbox), 0x0000ffff, 0.8, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT, 5, 5); } +static void +set_pos_and_anchor(SPCanvasText *canvas_text, const Geom::Piecewise > &pwd2, + const double t, const double length, bool use_curvature = false) +{ + using namespace Geom; + + Piecewise > pwd2_reparam = arc_length_parametrization(pwd2, 2 , 0.1); + double t_reparam = pwd2_reparam.cuts.back() * t; + Point pos = pwd2_reparam.valueAt(t_reparam); + Point dir = unit_vector(derivative(pwd2_reparam).valueAt(t_reparam)); + Point n = -rot90(dir); + double angle = Geom::angle_between(dir, Point(1,0)); + + sp_canvastext_set_coords(canvas_text, pos + n * length); + sp_canvastext_set_anchor(canvas_text, std::sin(angle), -std::cos(angle)); +} + +void +lpetool_create_measuring_items(SPLPEToolContext *lc, Inkscape::Selection *selection) +{ + bool show = prefs_get_int_attribute ("tools.lpetool", "show_measuring_info", 1) == 1 ? true : false; + if (!selection) { + selection = sp_desktop_selection(lc->desktop); + } + + SPPath *path; + SPCurve *curve; + SPCanvasText *canvas_text; + SPCanvasGroup *tmpgrp = sp_desktop_tempgroup(lc->desktop); + gchar *arc_length; + double lengthval; + + for (GSList const *i = selection->itemList(); i != NULL; i = i->next) { + if (SP_IS_PATH(i->data)) { + path = SP_PATH(i->data); + curve = sp_shape_get_curve(SP_SHAPE(path)); + Geom::Piecewise > pwd2 = paths_to_pw(curve->get_pathvector()); + canvas_text = (SPCanvasText *) sp_canvastext_new(tmpgrp, lc->desktop, Geom::Point(0,0), ""); + if (!show) + sp_canvas_item_hide(SP_CANVAS_ITEM(canvas_text)); + + SPUnitId unitid = static_cast(prefs_get_int_attribute("tools.lpetool", "unitid", SP_UNIT_PX)); + SPUnit unit = sp_unit_get_by_id(unitid); + + lengthval = Geom::length(pwd2); + gboolean success; + success = sp_convert_distance(&lengthval, &sp_unit_get_by_id(SP_UNIT_PX), &unit); + arc_length = g_strdup_printf("%.2f %s", lengthval, success ? sp_unit_get_abbreviation(&unit) : "px"); + sp_canvastext_set_text (canvas_text, arc_length); + set_pos_and_anchor(canvas_text, pwd2, 0.5, 10); + // TODO: must we free arc_length? + (*lc->measuring_items)[path] = SP_CANVAS_ITEM(canvas_text); + } + } +} + +void +lpetool_delete_measuring_items(SPLPEToolContext *lc) +{ + std::map::iterator i; + for (i = lc->measuring_items->begin(); i != lc->measuring_items->end(); ++i) { + gtk_object_destroy(GTK_OBJECT(i->second)); + } + lc->measuring_items->clear(); +} + +void +lpetool_update_measuring_items(SPLPEToolContext *lc) +{ + SPPath *path; + SPCurve *curve; + double lengthval; + gchar *arc_length; + std::map::iterator i; + for (i = lc->measuring_items->begin(); i != lc->measuring_items->end(); ++i) { + path = i->first; + curve = sp_shape_get_curve(SP_SHAPE(path)); + Geom::Piecewise > pwd2 = Geom::paths_to_pw(curve->get_pathvector()); + SPUnitId unitid = static_cast(prefs_get_int_attribute("tools.lpetool", "unitid", SP_UNIT_PX)); + SPUnit unit = sp_unit_get_by_id(unitid); + lengthval = Geom::length(pwd2); + gboolean success; + success = sp_convert_distance(&lengthval, &sp_unit_get_by_id(SP_UNIT_PX), &unit); + arc_length = g_strdup_printf("%.2f %s", lengthval, success ? sp_unit_get_abbreviation(&unit) : "px"); + sp_canvastext_set_text (SP_CANVASTEXT(i->second), arc_length); + set_pos_and_anchor(SP_CANVASTEXT(i->second), pwd2, 0.5, 10); + // TODO: must we free arc_length? + } +} + +void +lpetool_show_measuring_info(SPLPEToolContext *lc, bool show) +{ + std::map::iterator i; + for (i = lc->measuring_items->begin(); i != lc->measuring_items->end(); ++i) { + if (show) { + sp_canvas_item_show(i->second); + } else { + sp_canvas_item_hide(i->second); + } + } +} + /* Local Variables: mode:c++ diff --git a/src/lpe-tool-context.h b/src/lpe-tool-context.h index 8f46b3041..2c3e6e36f 100644 --- a/src/lpe-tool-context.h +++ b/src/lpe-tool-context.h @@ -16,6 +16,7 @@ */ #include "pen-context.h" +#include "helper/units.h" #define SP_TYPE_LPETOOL_CONTEXT (sp_lpetool_context_get_type()) #define SP_LPETOOL_CONTEXT(o) (GTK_CHECK_CAST((o), SP_TYPE_LPETOOL_CONTEXT, SPLPEToolContext)) @@ -36,6 +37,10 @@ enum LPEToolState { LPETOOL_STATE_NODE }; +namespace Inkscape { +class Selection; +} + class ShapeEditor; struct SPLPEToolContext : public SPPenContext { @@ -43,7 +48,10 @@ struct SPLPEToolContext : public SPPenContext { SPCanvasItem *canvas_bbox; Inkscape::LivePathEffect::EffectType mode; + std::map *measuring_items; + sigc::connection sel_changed_connection; + sigc::connection sel_modified_connection; }; struct SPLPEToolContextClass : public SPEventContextClass{}; @@ -54,6 +62,10 @@ bool lpetool_try_construction(SPLPEToolContext *lc, Inkscape::LivePathEffect::Ef void lpetool_context_switch_mode(SPLPEToolContext *lc, Inkscape::LivePathEffect::EffectType const type); void lpetool_get_limiting_bbox_corners(SPDocument *document, Geom::Point &A, Geom::Point &B); void lpetool_context_reset_limiting_bbox(SPLPEToolContext *lc); +void lpetool_create_measuring_items(SPLPEToolContext *lc, Inkscape::Selection *selection = NULL); +void lpetool_delete_measuring_items(SPLPEToolContext *lc); +void lpetool_update_measuring_items(SPLPEToolContext *lc); +void lpetool_show_measuring_info(SPLPEToolContext *lc, bool show = true); GType sp_lpetool_context_get_type(void); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 76ebb4ee1..5ddfa1bdf 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -449,6 +449,9 @@ static gchar const * ui_descr = " " " " " " + " " + " " + " " " " " " @@ -4830,36 +4833,49 @@ static void sp_lpetool_mode_changed(EgeSelectOneAction *act, GObject *tbl) } } +void +sp_lpetool_toolbox_sel_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) +{ + SPEventContext *ec = selection->desktop()->event_context; + if (!SP_IS_LPETOOL_CONTEXT(ec)) + return; + + lpetool_update_measuring_items(SP_LPETOOL_CONTEXT(ec)); +} + void sp_lpetool_toolbox_sel_changed(Inkscape::Selection *selection, GObject *tbl) { using namespace Inkscape::LivePathEffect; - { - GtkAction* w = GTK_ACTION(g_object_get_data(tbl, "lpetool_line_segment_action")); - SPItem *item = selection->singleItem(); - SPEventContext *ec = selection->desktop()->event_context; - if (!SP_IS_LPETOOL_CONTEXT(ec)) - return; - SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec); - if (item && SP_IS_LPE_ITEM(item) && lpetool_item_has_construction(lc, item)) { - SPLPEItem *lpeitem = SP_LPE_ITEM(item); - Effect* lpe = sp_lpe_item_get_current_lpe(lpeitem); - if (lpe && lpe->effectType() == LINE_SEGMENT) { - LPELineSegment *lpels = static_cast(lpe); - g_object_set_data(tbl, "currentlpe", lpe); - g_object_set_data(tbl, "currentlpeitem", lpeitem); - gtk_action_set_sensitive(w, TRUE); - ege_select_one_action_set_active(EGE_SELECT_ONE_ACTION(w), lpels->end_type.get_value()); - } else { - g_object_set_data(tbl, "currentlpe", NULL); - g_object_set_data(tbl, "currentlpeitem", NULL); - gtk_action_set_sensitive(w, FALSE); - } + SPEventContext *ec = selection->desktop()->event_context; + if (!SP_IS_LPETOOL_CONTEXT(ec)) + return; + SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(ec); + + lpetool_delete_measuring_items(lc); + lpetool_create_measuring_items(lc, selection); + + // activate line segment combo box if a single item with LPELineSegment is selected + GtkAction* w = GTK_ACTION(g_object_get_data(tbl, "lpetool_line_segment_action")); + SPItem *item = selection->singleItem(); + if (item && SP_IS_LPE_ITEM(item) && lpetool_item_has_construction(lc, item)) { + SPLPEItem *lpeitem = SP_LPE_ITEM(item); + Effect* lpe = sp_lpe_item_get_current_lpe(lpeitem); + if (lpe && lpe->effectType() == LINE_SEGMENT) { + LPELineSegment *lpels = static_cast(lpe); + g_object_set_data(tbl, "currentlpe", lpe); + g_object_set_data(tbl, "currentlpeitem", lpeitem); + gtk_action_set_sensitive(w, TRUE); + ege_select_one_action_set_active(EGE_SELECT_ONE_ACTION(w), lpels->end_type.get_value()); } else { g_object_set_data(tbl, "currentlpe", NULL); g_object_set_data(tbl, "currentlpeitem", NULL); gtk_action_set_sensitive(w, FALSE); } + } else { + g_object_set_data(tbl, "currentlpe", NULL); + g_object_set_data(tbl, "currentlpeitem", NULL); + gtk_action_set_sensitive(w, FALSE); } } @@ -4876,6 +4892,34 @@ lpetool_toggle_show_bbox (GtkToggleAction *act, gpointer data) { } } +static void +lpetool_toggle_show_measuring_info (GtkToggleAction *act, gpointer data) { + SPDesktop *desktop = static_cast(data); + if (!tools_isactive(desktop, TOOLS_LPETOOL)) + return; + + SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context); + if (tools_isactive(desktop, TOOLS_LPETOOL)) { + bool show = gtk_toggle_action_get_active( act ); + prefs_set_int_attribute ("tools.lpetool", "show_measuring_info", show ? 1 : 0); + lpetool_show_measuring_info(lc, show); + } +} + +static void +lpetool_unit_changed(GtkAction* act, GObject* tbl) { + UnitTracker* tracker = reinterpret_cast(g_object_get_data(tbl, "tracker")); + SPUnit const *unit = tracker->getActiveUnit(); + prefs_set_int_attribute("tools.lpetool", "unitid", unit->unit_id); + + SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" ); + if (SP_IS_LPETOOL_CONTEXT(desktop->event_context)) { + SPLPEToolContext *lc = SP_LPETOOL_CONTEXT(desktop->event_context); + lpetool_delete_measuring_items(lc); + lpetool_create_measuring_items(lc); + } +} + static void lpetool_toggle_set_bbox (GtkToggleAction *act, gpointer data) { SPDesktop *desktop = static_cast(data); @@ -4952,6 +4996,12 @@ sp_lpetool_change_line_segment_type(EgeSelectOneAction* act, GObject* tbl) { static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { + UnitTracker* tracker = new UnitTracker(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE); + tracker->setActiveUnit(sp_desktop_namedview(desktop)->doc_units); + g_object_set_data(holder, "tracker", tracker); + SPUnit const *unit = tracker->getActiveUnit(); + prefs_set_int_attribute("tools.lpetool", "unitid", unit->unit_id); + /** Automatically create a list of LPEs that get added to the toolbar **/ { GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); @@ -5034,9 +5084,33 @@ static void sp_lpetool_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActi gtk_action_group_add_action(mainActions, GTK_ACTION(act)); } + /* Display measuring info for selected items */ + { + InkToggleAction* act = ink_toggle_action_new( "LPEMeasuringAction", + _("Display measuring info"), + _("Display measuring info for selected items"), + "lpetool_measuring_info", + Inkscape::ICON_SIZE_DECORATION ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(lpetool_toggle_show_measuring_info), desktop ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.lpetool", "show_measuring_info", 1 ) ); + } + + // add the units menu + { + GtkAction* act = tracker->createAction( "LPEToolUnitsAction", _("Units"), ("") ); + gtk_action_group_add_action( mainActions, act ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(lpetool_unit_changed), (GObject*)holder ); + } + //watch selection Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISNodeToolbox"); + sigc::connection *c_selection_modified = + new sigc::connection (sp_desktop_selection (desktop)->connectModified + (sigc::bind (sigc::ptr_fun (sp_lpetool_toolbox_sel_modified), (GObject*)holder))); + pool->add_connection ("selection-modified", c_selection_modified); + sigc::connection *c_selection_changed = new sigc::connection (sp_desktop_selection (desktop)->connectChanged (sigc::bind (sigc::ptr_fun(sp_lpetool_toolbox_sel_changed), (GObject*)holder)));