From 54dcba355d650c72c845711e0c857734f8d5d5b6 Mon Sep 17 00:00:00 2001 From: Geoff Lankow Date: Sat, 18 Nov 2017 17:22:01 +1300 Subject: Add arc radius to toolbar --- src/widgets/arc-toolbar.cpp | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 23e1eba1a..77bfdaf01 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -45,15 +45,20 @@ #include "toolbox.h" #include "ui/icon-names.h" #include "ui/uxmanager.h" +#include "ui/widget/unit-tracker.h" #include "ui/tools/arc-tool.h" #include "verbs.h" #include "widgets/spinbutton-events.h" +#include "widgets/widget-sizes.h" #include "xml/node-event-vector.h" +using Inkscape::UI::Widget::UnitTracker; using Inkscape::UI::UXManager; using Inkscape::DocumentUndo; using Inkscape::UI::ToolboxFactory; using Inkscape::UI::PrefPusher; +using Inkscape::Util::Quantity; +using Inkscape::Util::unit_table; //######################## //## Circle / Arc ## @@ -75,6 +80,72 @@ static void sp_arctb_sensitivize( GObject *tbl, double v1, double v2 ) } } +static void sp_arctb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name) +{ + SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); + + UnitTracker* tracker = reinterpret_cast(g_object_get_data( tbl, "tracker" )); + Unit const *unit = tracker->getActiveUnit(); + g_return_if_fail(unit != NULL); + + SPDocument* document = desktop->getDocument(); + Geom::Scale scale = document->getDocumentScale(); + + if (DocumentUndo::getUndoSensitive(document)) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setDouble(Glib::ustring("/tools/shapes/arc/") + value_name, + Quantity::convert(gtk_adjustment_get_value(adj), unit, "px")); + } + + // quit if run by the attr_changed listener + if (g_object_get_data( tbl, "freeze" ) || tracker->isUpdating()) { + return; + } + + // in turn, prevent listener from responding + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE)); + + bool modmade = false; + Inkscape::Selection *selection = desktop->getSelection(); + auto itemlist= selection->items(); + for(auto i=itemlist.begin();i!=itemlist.end();++i){ + SPItem *item = *i; + if (SP_IS_GENERICELLIPSE(item)) { + + SPGenericEllipse *ge = SP_GENERICELLIPSE(item); + + if (!strcmp(value_name, "rx")) { + ge->rx = Quantity::convert(gtk_adjustment_get_value(adj), unit, "px") / scale[Geom::X]; + } else { + ge->ry = Quantity::convert(gtk_adjustment_get_value(adj), unit, "px") / scale[Geom::Y]; + } + + ge->normalize(); + (SP_OBJECT(ge))->updateRepr(); + (SP_OBJECT(ge))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + + modmade = true; + } + } + + if (modmade) { + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_ARC, + _("Change arc")); + } + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + +static void sp_arctb_rx_value_changed(GtkAdjustment *adj, GObject *tbl) +{ + sp_arctb_value_changed(adj, tbl, "rx"); +} + +static void sp_arctb_ry_value_changed(GtkAdjustment *adj, GObject *tbl) +{ + sp_arctb_value_changed(adj, tbl, "ry"); +} + static void sp_arctb_startend_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name, gchar const *other_name) { @@ -204,6 +275,14 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) static void sp_arctb_defaults(GtkWidget *, GObject *obj) { GtkAdjustment *adj; + adj = GTK_ADJUSTMENT( g_object_get_data(obj, "rx") ); + gtk_adjustment_set_value(adj, 0.0); + gtk_adjustment_value_changed(adj); + + adj = GTK_ADJUSTMENT( g_object_get_data(obj, "ry") ); + gtk_adjustment_set_value(adj, 0.0); + gtk_adjustment_value_changed(adj); + adj = GTK_ADJUSTMENT( g_object_get_data(obj, "start") ); gtk_adjustment_set_value(adj, 0.0); gtk_adjustment_value_changed(adj); @@ -229,6 +308,34 @@ static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * / // in turn, prevent callbacks from responding g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + UnitTracker* tracker = reinterpret_cast( g_object_get_data( tbl, "tracker" ) ); + Unit const *unit = tracker->getActiveUnit(); + g_return_if_fail(unit != NULL); + + gdouble radius = 0; + gdouble rx = 0; + gdouble ry = 0; + sp_repr_get_double(repr, "r", &radius); + if (radius) { + rx = ry = radius; + } else { + sp_repr_get_double(repr, "rx", &rx); + sp_repr_get_double(repr, "ry", &ry); + } + + SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); + SPDocument* document = desktop->getDocument(); + Geom::Scale scale = document->getDocumentScale(); + + GtkAdjustment *adj; + adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "rx") ); + gtk_adjustment_set_value(adj, Quantity::convert(rx, "px", unit) * scale[Geom::X]); + gtk_adjustment_value_changed(adj); + + adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "ry") ); + gtk_adjustment_set_value(adj, Quantity::convert(ry, "px", unit) * scale[Geom::Y]); + gtk_adjustment_value_changed(adj); + gdouble start = 0.; gdouble end = 0.; sp_repr_get_double(repr, "sodipodi:start", &start); @@ -297,6 +404,11 @@ static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GOb g_object_set_data( tbl, "single", GINT_TO_POINTER(TRUE) ); g_object_set( G_OBJECT(act), "label", _("Change:"), NULL ); + GtkAction* rx = GTK_ACTION( g_object_get_data( tbl, "rx_action" ) ); + gtk_action_set_sensitive(rx, TRUE); + GtkAction* ry = GTK_ACTION( g_object_get_data( tbl, "ry_action" ) ); + gtk_action_set_sensitive(ry, TRUE); + if (repr) { g_object_set_data( tbl, "repr", repr ); Inkscape::GC::anchor(repr); @@ -320,6 +432,9 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec EgeAdjustmentAction* eact = 0; GtkIconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); + UnitTracker* tracker = new UnitTracker(Inkscape::Util::UNIT_TYPE_LINEAR); + tracker->setActiveUnit(unit_table.getUnit("px")); + g_object_set_data( holder, "tracker", tracker ); { EgeOutputAction* act = ege_output_action_new( "ArcStateAction", _("New:"), "", 0 ); @@ -328,6 +443,46 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec g_object_set_data( holder, "mode_action", act ); } + /* Radius X */ + { + gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500}; + eact = create_adjustment_action( "ArcRadiusXAction", + _("Radius X"), _("Rx:"), _("X Radius of arc"), + "/tools/shapes/arc/rx", 0, + GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-arc", + 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, + labels, values, G_N_ELEMENTS(labels), + sp_arctb_rx_value_changed, tracker); + tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); + g_object_set_data( holder, "rx_action", eact ); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + } + + /* Radius Y */ + { + gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500}; + eact = create_adjustment_action( "ArcRadiusYAction", + _("Radius Y"), _("Ry:"), _("Y Radius of arc"), + "/tools/shapes/arc/ry", 0, + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, + 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, + labels, values, G_N_ELEMENTS(labels), + sp_arctb_ry_value_changed, tracker); + tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); + g_object_set_data( holder, "ry_action", eact ); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + } + + // add the units menu + { + GtkAction* act = tracker->createAction( "ArcUnitsAction", _("Units"), ("") ); + gtk_action_group_add_action( mainActions, act ); + } + /* Start */ { eact = create_adjustment_action( "ArcStartAction", -- cgit v1.2.3 From 28552a7f1c2cfe77521602a4147b99a7f87a30d4 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 22:22:18 +0100 Subject: Do not reset rx/cx to zero when resetting arc to whole ellipse --- src/widgets/arc-toolbar.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 77bfdaf01..fd8ba0343 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -275,13 +275,6 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) static void sp_arctb_defaults(GtkWidget *, GObject *obj) { GtkAdjustment *adj; - adj = GTK_ADJUSTMENT( g_object_get_data(obj, "rx") ); - gtk_adjustment_set_value(adj, 0.0); - gtk_adjustment_value_changed(adj); - - adj = GTK_ADJUSTMENT( g_object_get_data(obj, "ry") ); - gtk_adjustment_set_value(adj, 0.0); - gtk_adjustment_value_changed(adj); adj = GTK_ADJUSTMENT( g_object_get_data(obj, "start") ); gtk_adjustment_set_value(adj, 0.0); -- cgit v1.2.3 From 12a2f445e64e08e7d2dd12fde2ee17467238ebf9 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 23:08:51 +0100 Subject: Account for Inkscape's custom arcs (which do not have cx/cy) If an open arc is rendered we need to look at the prefixed values instead. --- src/widgets/arc-toolbar.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index fd8ba0343..77f74b348 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -315,6 +315,10 @@ static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * / sp_repr_get_double(repr, "rx", &rx); sp_repr_get_double(repr, "ry", &ry); } + if (!rx) { + sp_repr_get_double(repr, "sodipodi:rx", &rx); + sp_repr_get_double(repr, "sodipodi:ry", &ry); + } SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); SPDocument* document = desktop->getDocument(); -- cgit v1.2.3 From dfad76343452004bb06c92d19262d22dc3cb9e76 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 23:15:36 +0100 Subject: Prevent setting zero radius While the spec explicitly allows for that (and it should disable rendering of the element) Inkscape does not allow setting a zero radius at runtime (it works fine when opening an existing file). If we still force this during runtime we end up with a "ghost" ellipse on canvas which looks as if it had the old radius but has control points according to the zero radius and has the added bonus of not being movable (or rather being movable but snapping back back immediately when released) until updating the radius with a valid number again which finally moves the ellipse to wherever it should have been. --- src/widgets/arc-toolbar.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 77f74b348..0e503cd5e 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -82,6 +82,13 @@ static void sp_arctb_sensitivize( GObject *tbl, double v1, double v2 ) static void sp_arctb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name) { + // Per SVG spec "a [radius] value of zero disables rendering of the element". + // However our implementation does not allow a setting of zero in the UI (not even in the XML editor) + // and ugly things happen if it's forced here, so better leave the properties untouched. + if (!gtk_adjustment_get_value(adj)) { + return; + } + SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); UnitTracker* tracker = reinterpret_cast(g_object_get_data( tbl, "tracker" )); -- cgit v1.2.3 From 01d6520bcf68b688ca49b048ffd3a81044c3b135 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 23:36:13 +0100 Subject: Change labels a bit for consistency with other UI strings --- src/widgets/arc-toolbar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 0e503cd5e..3faea1750 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -452,7 +452,7 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500}; eact = create_adjustment_action( "ArcRadiusXAction", - _("Radius X"), _("Rx:"), _("X Radius of arc"), + _("Horizontal radius"), _("Rx:"), _("Horizontal radius of the circle, ellipse, or arc"), "/tools/shapes/arc/rx", 0, GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-arc", 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, @@ -469,7 +469,7 @@ void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObjec gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500}; eact = create_adjustment_action( "ArcRadiusYAction", - _("Radius Y"), _("Ry:"), _("Y Radius of arc"), + _("Vertical radius"), _("Ry:"), _("Vertical radius of the circle, ellipse, or arc"), "/tools/shapes/arc/ry", 0, GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, 0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, -- cgit v1.2.3 From d1395472c4b20d4e4763364b61e3d6caedb29444 Mon Sep 17 00:00:00 2001 From: Geoff Lankow Date: Tue, 5 Dec 2017 12:35:57 +1300 Subject: Add arc radius to toolbar --- src/widgets/arc-toolbar.cpp | 57 ++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'src/widgets/arc-toolbar.cpp') diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 3faea1750..907285a60 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -122,9 +122,9 @@ static void sp_arctb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const SPGenericEllipse *ge = SP_GENERICELLIPSE(item); if (!strcmp(value_name, "rx")) { - ge->rx = Quantity::convert(gtk_adjustment_get_value(adj), unit, "px") / scale[Geom::X]; + ge->setVisibleRx(Quantity::convert(gtk_adjustment_get_value(adj), unit, "px")); } else { - ge->ry = Quantity::convert(gtk_adjustment_get_value(adj), unit, "px") / scale[Geom::Y]; + ge->setVisibleRy(Quantity::convert(gtk_adjustment_get_value(adj), unit, "px")); } ge->normalize(); @@ -308,37 +308,25 @@ static void arc_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const * / // in turn, prevent callbacks from responding g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); - UnitTracker* tracker = reinterpret_cast( g_object_get_data( tbl, "tracker" ) ); - Unit const *unit = tracker->getActiveUnit(); - g_return_if_fail(unit != NULL); - - gdouble radius = 0; - gdouble rx = 0; - gdouble ry = 0; - sp_repr_get_double(repr, "r", &radius); - if (radius) { - rx = ry = radius; - } else { - sp_repr_get_double(repr, "rx", &rx); - sp_repr_get_double(repr, "ry", &ry); - } - if (!rx) { - sp_repr_get_double(repr, "sodipodi:rx", &rx); - sp_repr_get_double(repr, "sodipodi:ry", &ry); - } + gpointer item = g_object_get_data( tbl, "item" ); + if (item && SP_IS_GENERICELLIPSE(item)) { + SPGenericEllipse *ge = SP_GENERICELLIPSE(item); - SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); - SPDocument* document = desktop->getDocument(); - Geom::Scale scale = document->getDocumentScale(); + UnitTracker* tracker = reinterpret_cast( g_object_get_data( tbl, "tracker" ) ); + Unit const *unit = tracker->getActiveUnit(); + g_return_if_fail(unit != NULL); - GtkAdjustment *adj; - adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "rx") ); - gtk_adjustment_set_value(adj, Quantity::convert(rx, "px", unit) * scale[Geom::X]); - gtk_adjustment_value_changed(adj); + GtkAdjustment *adj; + adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "rx") ); + gdouble rx = ge->getVisibleRx(); + gtk_adjustment_set_value(adj, Quantity::convert(rx, "px", unit)); + gtk_adjustment_value_changed(adj); - adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "ry") ); - gtk_adjustment_set_value(adj, Quantity::convert(ry, "px", unit) * scale[Geom::Y]); - gtk_adjustment_value_changed(adj); + adj = GTK_ADJUSTMENT( g_object_get_data(tbl, "ry") ); + gdouble ry = ge->getVisibleRy(); + gtk_adjustment_set_value(adj, Quantity::convert(ry, "px", unit)); + gtk_adjustment_value_changed(adj); + } gdouble start = 0.; gdouble end = 0.; @@ -387,14 +375,18 @@ static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GOb { int n_selected = 0; Inkscape::XML::Node *repr = NULL; + SPItem *item = NULL; + if ( g_object_get_data( tbl, "repr" ) ) { + g_object_set_data( tbl, "item", NULL ); + } purge_repr_listener( tbl, tbl ); auto itemlist= selection->items(); for(auto i=itemlist.begin();i!=itemlist.end();++i){ - SPItem *item = *i; - if (SP_IS_GENERICELLIPSE(item)) { + if (SP_IS_GENERICELLIPSE(*i)) { n_selected++; + item = *i; repr = item->getRepr(); } } @@ -415,6 +407,7 @@ static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GOb if (repr) { g_object_set_data( tbl, "repr", repr ); + g_object_set_data( tbl, "item", item ); Inkscape::GC::anchor(repr); sp_repr_add_listener(repr, &arc_tb_repr_events, tbl); sp_repr_synthesize_events(repr, &arc_tb_repr_events, tbl); -- cgit v1.2.3