summaryrefslogtreecommitdiffstats
path: root/src/ui/toolbar/box3d-toolbar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/toolbar/box3d-toolbar.cpp')
-rw-r--r--src/ui/toolbar/box3d-toolbar.cpp561
1 files changed, 279 insertions, 282 deletions
diff --git a/src/ui/toolbar/box3d-toolbar.cpp b/src/ui/toolbar/box3d-toolbar.cpp
index fb59b13b9..50838a393 100644
--- a/src/ui/toolbar/box3d-toolbar.cpp
+++ b/src/ui/toolbar/box3d-toolbar.cpp
@@ -58,168 +58,176 @@ using Inkscape::UI::PrefPusher;
//## 3D Box ##
//########################
-// normalize angle so that it lies in the interval [0,360]
-static double box3d_normalize_angle (double a) {
- double angle = a + ((int) (a/360.0))*360;
- if (angle < 0) {
- angle += 360.0;
- }
- return angle;
-}
-static void box3d_set_button_and_adjustment(Persp3D *persp,
- Proj::Axis axis,
- GtkAdjustment *adj,
- GtkAction *act,
- GtkToggleAction *tact)
-{
- // TODO: Take all selected perspectives into account but don't touch the state button if not all of them
- // have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states
- // are reset).
- bool is_infinite = !persp3d_VP_is_finite(persp->perspective_impl, axis);
-
- if (is_infinite) {
- gtk_toggle_action_set_active(tact, TRUE);
- gtk_action_set_sensitive(act, TRUE);
- double angle = persp3d_get_infinite_angle(persp, axis);
- if (angle != Geom::infinity()) { // FIXME: We should catch this error earlier (don't show the spinbutton at all)
- gtk_adjustment_set_value(adj, box3d_normalize_angle(angle));
- }
- } else {
- gtk_toggle_action_set_active(tact, FALSE);
- gtk_action_set_sensitive(act, FALSE);
- }
-}
+static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events =
+{
+ nullptr, /* child_added */
+ nullptr, /* child_removed */
+ Inkscape::UI::Toolbar::Box3DToolbar::event_attr_changed,
+ nullptr, /* content_changed */
+ nullptr /* order_changed */
+};
-static void box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data)
+namespace Inkscape {
+namespace UI {
+namespace Toolbar {
+GtkWidget *
+Box3DToolbar::prep(SPDesktop *desktop, GtkActionGroup* mainActions)
{
- if (!persp_repr) {
- g_print ("No perspective given to box3d_resync_toolbar().\n");
- return;
- }
+ auto holder = new Box3DToolbar(desktop);
- GtkWidget *tbl = GTK_WIDGET(data);
- GtkAdjustment *adj = nullptr;
- GtkAction *act = nullptr;
- GtkToggleAction *tact = nullptr;
- Persp3D *persp = persp3d_get_from_repr(persp_repr);
- if (!persp) {
- // Hmm, is it an error if this happens?
- return;
- }
- {
- adj = GTK_ADJUSTMENT(g_object_get_data(G_OBJECT(tbl), "box3d_angle_x"));
- act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_x_action"));
- tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_x_state_action"))->action;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ SPDocument *document = desktop->getDocument();
+ Persp3DImpl *persp_impl = document->getCurrentPersp3DImpl();
- box3d_set_button_and_adjustment(persp, Proj::X, adj, act, tact);
- }
+ /* Angle X */
{
- adj = GTK_ADJUSTMENT(g_object_get_data(G_OBJECT(tbl), "box3d_angle_y"));
- act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_y_action"));
- tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_y_state_action"))->action;
-
- box3d_set_button_and_adjustment(persp, Proj::Y, adj, act, tact);
+ gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
+ holder->_angle_x_action = create_adjustment_action( "3DBoxAngleXAction",
+ _("Angle in X direction"), _("Angle X:"),
+ // Translators: PL is short for 'perspective line'
+ _("Angle of PLs in X direction"),
+ "/tools/shapes/3dbox/box3d_angle_x", 30,
+ GTK_WIDGET(desktop->canvas),
+ nullptr, // dataKludge
+ TRUE, "altx-box3d",
+ -360.0, 360.0, 1.0, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ nullptr // callback
+ );
+ holder->_angle_x_adj = Glib::wrap(ege_adjustment_action_get_adjustment(holder->_angle_x_action));
+ holder->_angle_x_adj->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*holder, &Box3DToolbar::angle_value_changed),
+ holder->_angle_x_adj, Proj::X));
+ gtk_action_group_add_action( mainActions, GTK_ACTION(holder->_angle_x_action) );
}
- {
- adj = GTK_ADJUSTMENT(g_object_get_data(G_OBJECT(tbl), "box3d_angle_z"));
- act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_z_action"));
- tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_z_state_action"))->action;
- box3d_set_button_and_adjustment(persp, Proj::Z, adj, act, tact);
+ if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::X)) {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_x_action), TRUE );
+ } else {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_x_action), FALSE );
}
-}
-static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr,
- gchar const * /*name*/,
- gchar const * /*old_value*/,
- gchar const * /*new_value*/,
- bool /*is_interactive*/,
- gpointer data)
-{
- GtkWidget *tbl = GTK_WIDGET(data);
- // quit if run by the attr_changed or selection changed listener
- if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
- return;
+ /* VP X state */
+ {
+ holder->_vp_x_state_action = ink_toggle_action_new( "3DBoxVPXStateAction",
+ // Translators: VP is short for 'vanishing point'
+ _("State of VP in X direction"),
+ _("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"),
+ INKSCAPE_ICON("perspective-parallel"),
+ GTK_ICON_SIZE_MENU );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( holder->_vp_x_state_action ) );
+ g_signal_connect_after( G_OBJECT(holder->_vp_x_state_action), "toggled", G_CALLBACK(Box3DToolbar::vp_state_changed), (gpointer)Proj::X );
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_x_action), !prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(holder->_vp_x_state_action), prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
}
- // set freeze so that it can be caught in box3d_angle_z_value_changed() (to avoid calling
- // SPDocumentUndo::maybeDone() when the document is undo insensitive)
- g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
-
- // TODO: Only update the appropriate part of the toolbar
-// if (!strcmp(name, "inkscape:vp_z")) {
- box3d_resync_toolbar(repr, G_OBJECT(tbl));
-// }
-
- Persp3D *persp = persp3d_get_from_repr(repr);
- persp3d_update_box_reprs(persp);
+ /* Angle Y */
+ {
+ gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
+ holder->_angle_y_action = create_adjustment_action( "3DBoxAngleYAction",
+ _("Angle in Y direction"), _("Angle Y:"),
+ // Translators: PL is short for 'perspective line'
+ _("Angle of PLs in Y direction"),
+ "/tools/shapes/3dbox/box3d_angle_y", 30,
+ GTK_WIDGET(desktop->canvas),
+ nullptr, // dataKludge
+ FALSE, nullptr,
+ -360.0, 360.0, 1.0, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ nullptr // callback
+ );
+ holder->_angle_y_adj = Glib::wrap(ege_adjustment_action_get_adjustment(holder->_angle_y_action));
+ holder->_angle_y_adj->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*holder, &Box3DToolbar::angle_value_changed),
+ holder->_angle_y_adj, Proj::Y));
+ gtk_action_group_add_action( mainActions, GTK_ACTION(holder->_angle_y_action) );
+ }
- g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE));
-}
+ if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Y)) {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_y_action), TRUE );
+ } else {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_y_action), FALSE );
+ }
-static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events =
-{
- nullptr, /* child_added */
- nullptr, /* child_removed */
- box3d_persp_tb_event_attr_changed,
- nullptr, /* content_changed */
- nullptr /* order_changed */
-};
+ /* VP Y state */
+ {
+ holder->_vp_y_state_action = ink_toggle_action_new( "3DBoxVPYStateAction",
+ // Translators: VP is short for 'vanishing point'
+ _("State of VP in Y direction"),
+ _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
+ INKSCAPE_ICON("perspective-parallel"),
+ GTK_ICON_SIZE_MENU );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( holder->_vp_y_state_action ) );
+ g_signal_connect_after( G_OBJECT(holder->_vp_y_state_action), "toggled", G_CALLBACK(Box3DToolbar::vp_state_changed), (gpointer)Proj::Y);
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_y_action), !prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(holder->_vp_y_state_action), prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
+ }
-/**
- * \param selection Should not be NULL.
- */
-// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each
-// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?)
-static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
-{
- // Here the following should be done: If all selected boxes have finite VPs in a certain direction,
- // disable the angle entry fields for this direction (otherwise entering a value in them should only
- // update the perspectives with infinite VPs and leave the other ones untouched).
+ /* Angle Z */
+ {
+ gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
+ holder->_angle_z_action = create_adjustment_action( "3DBoxAngleZAction",
+ _("Angle in Z direction"), _("Angle Z:"),
+ // Translators: PL is short for 'perspective line'
+ _("Angle of PLs in Z direction"),
+ "/tools/shapes/3dbox/box3d_angle_z", 30,
+ GTK_WIDGET(desktop->canvas),
+ nullptr, // dataKludge
+ FALSE, nullptr,
+ -360.0, 360.0, 1.0, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ nullptr // callback
+ );
+ holder->_angle_z_adj = Glib::wrap(ege_adjustment_action_get_adjustment(holder->_angle_z_action));
+ holder->_angle_z_adj->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*holder, &Box3DToolbar::angle_value_changed),
+ holder->_angle_z_adj, Proj::Z));
+ gtk_action_group_add_action( mainActions, GTK_ACTION(holder->_angle_z_action) );
+ }
- Inkscape::XML::Node *persp_repr = nullptr;
- purge_repr_listener(tbl, tbl);
+ if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Z)) {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_z_action), TRUE );
+ } else {
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_z_action), FALSE );
+ }
- SPItem *item = selection->singleItem();
- SPBox3D *box = dynamic_cast<SPBox3D *>(item);
- if (box) {
- // FIXME: Also deal with multiple selected boxes
- Persp3D *persp = box3d_get_perspective(box);
- persp_repr = persp->getRepr();
- if (persp_repr) {
- g_object_set_data(tbl, "repr", persp_repr);
- Inkscape::GC::anchor(persp_repr);
- sp_repr_add_listener(persp_repr, &box3d_persp_tb_repr_events, tbl);
- sp_repr_synthesize_events(persp_repr, &box3d_persp_tb_repr_events, tbl);
+ /* VP Z state */
+ {
+ holder->_vp_z_state_action = ink_toggle_action_new( "3DBoxVPZStateAction",
+ // Translators: VP is short for 'vanishing point'
+ _("State of VP in Z direction"),
+ _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
+ INKSCAPE_ICON("perspective-parallel"),
+ GTK_ICON_SIZE_MENU );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( holder->_vp_z_state_action ) );
+ g_signal_connect_after( G_OBJECT(holder->_vp_z_state_action), "toggled", G_CALLBACK(Box3DToolbar::vp_state_changed), (gpointer)Proj::Z );
+ gtk_action_set_sensitive( GTK_ACTION(holder->_angle_z_action), !prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(holder->_vp_z_state_action), prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
+ }
- SP_ACTIVE_DOCUMENT->setCurrentPersp3D(persp3d_get_from_repr(persp_repr));
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setString("/tools/shapes/3dbox/persp", persp_repr->attribute("id"));
+ desktop->connectEventContextChanged(sigc::mem_fun(*holder, &Box3DToolbar::check_ec));
- g_object_set_data(tbl, "freeze", GINT_TO_POINTER(TRUE));
- box3d_resync_toolbar(persp_repr, tbl);
- g_object_set_data(tbl, "freeze", GINT_TO_POINTER(FALSE));
- }
- }
+ return GTK_WIDGET(holder->gobj());
}
-static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis)
+void
+Box3DToolbar::angle_value_changed(Glib::RefPtr<Gtk::Adjustment> &adj,
+ Proj::Axis axis)
{
- SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( dataKludge, "desktop" ));
- SPDocument *document = desktop->getDocument();
+ SPDocument *document = _desktop->getDocument();
// quit if run by the attr_changed or selection changed listener
- if (g_object_get_data( dataKludge, "freeze" )) {
+ if (_freeze) {
return;
}
// in turn, prevent listener from responding
- g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE));
+ _freeze = true;
- std::list<Persp3D *> sel_persps = desktop->getSelection()->perspList();
+ std::list<Persp3D *> sel_persps = _desktop->getSelection()->perspList();
if (sel_persps.empty()) {
// this can happen when the document is created; we silently ignore it
return;
@@ -227,33 +235,18 @@ static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, P
Persp3D *persp = sel_persps.front();
persp->perspective_impl->tmat.set_infinite_direction (axis,
- gtk_adjustment_get_value(adj));
+ adj->get_value());
persp->updateRepr();
// TODO: use the correct axis here, too
DocumentUndo::maybeDone(document, "perspangle", SP_VERB_CONTEXT_3DBOX, _("3D Box: Change perspective (angle of infinite axis)"));
- g_object_set_data( dataKludge, "freeze", GINT_TO_POINTER(FALSE) );
+ _freeze = false;
}
-
-static void box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge)
-{
- box3d_angle_value_changed(adj, dataKludge, Proj::X);
-}
-
-static void box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge)
-{
- box3d_angle_value_changed(adj, dataKludge, Proj::Y);
-}
-
-static void box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge)
-{
- box3d_angle_value_changed(adj, dataKludge, Proj::Z);
-}
-
-
-static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction * /*box3d_angle*/, Proj::Axis axis )
+void
+Box3DToolbar::vp_state_changed(GtkToggleAction *act,
+ Proj::Axis axis )
{
// TODO: Take all selected perspectives into account
std::list<Persp3D *> sel_persps = SP_ACTIVE_DESKTOP->getSelection()->perspList();
@@ -267,167 +260,171 @@ static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction * /*box3d_an
persp3d_set_VP_state (persp, axis, set_infinite ? Proj::VP_INFINITE : Proj::VP_FINITE);
}
-static void box3d_vp_x_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
+void
+Box3DToolbar::check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec)
{
- box3d_vp_state_changed(act, box3d_angle, Proj::X);
-}
-
-static void box3d_vp_y_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
-{
- box3d_vp_state_changed(act, box3d_angle, Proj::Y);
+ if (SP_IS_BOX3D_CONTEXT(ec)) {
+ _changed = desktop->getSelection()->connectChanged(sigc::mem_fun(*this, &Box3DToolbar::selection_changed));
+ selection_changed(desktop->getSelection());
+ } else {
+ if (_changed)
+ _changed.disconnect();
+ }
}
-static void box3d_vp_z_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
+Box3DToolbar::~Box3DToolbar()
{
- box3d_vp_state_changed(act, box3d_angle, Proj::Z);
+ if (_repr) { // remove old listener
+ _repr->removeListenerByData(this);
+ Inkscape::GC::release(_repr);
+ _repr = nullptr;
+ }
}
-static void box3d_toolbox_check_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
-
-void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
+/**
+ * \param selection Should not be NULL.
+ */
+// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each
+// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?)
+void
+Box3DToolbar::selection_changed(Inkscape::Selection *selection)
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- EgeAdjustmentAction* eact = nullptr;
- SPDocument *document = desktop->getDocument();
- Persp3DImpl *persp_impl = document->getCurrentPersp3DImpl();
+ // Here the following should be done: If all selected boxes have finite VPs in a certain direction,
+ // disable the angle entry fields for this direction (otherwise entering a value in them should only
+ // update the perspectives with infinite VPs and leave the other ones untouched).
- EgeAdjustmentAction* box3d_angle_x = nullptr;
- EgeAdjustmentAction* box3d_angle_y = nullptr;
- EgeAdjustmentAction* box3d_angle_z = nullptr;
+ Inkscape::XML::Node *persp_repr = nullptr;
- /* Angle X */
- {
- gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
- gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
- eact = create_adjustment_action( "3DBoxAngleXAction",
- _("Angle in X direction"), _("Angle X:"),
- // Translators: PL is short for 'perspective line'
- _("Angle of PLs in X direction"),
- "/tools/shapes/3dbox/box3d_angle_x", 30,
- GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-box3d",
- -360.0, 360.0, 1.0, 10.0,
- labels, values, G_N_ELEMENTS(labels),
- box3d_angle_x_value_changed );
- gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
- g_object_set_data( holder, "box3d_angle_x_action", eact );
- box3d_angle_x = eact;
+ if (_repr) { // remove old listener
+ _repr->removeListenerByData(this);
+ Inkscape::GC::release(_repr);
+ _repr = nullptr;
}
- if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::X)) {
- gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
- } else {
- gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
- }
+ SPItem *item = selection->singleItem();
+ SPBox3D *box = dynamic_cast<SPBox3D *>(item);
+ if (box) {
+ // FIXME: Also deal with multiple selected boxes
+ Persp3D *persp = box3d_get_perspective(box);
+ persp_repr = persp->getRepr();
+ if (persp_repr) {
+ _repr = persp_repr;
+ Inkscape::GC::anchor(_repr);
+ _repr->addListener(&box3d_persp_tb_repr_events, this);
+ _repr->synthesizeEvents(&box3d_persp_tb_repr_events, this);
+ SP_ACTIVE_DOCUMENT->setCurrentPersp3D(persp3d_get_from_repr(_repr));
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setString("/tools/shapes/3dbox/persp", _repr->attribute("id"));
- /* VP X state */
- {
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXStateAction",
- // Translators: VP is short for 'vanishing point'
- _("State of VP in X direction"),
- _("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"),
- INKSCAPE_ICON("perspective-parallel"),
- GTK_ICON_SIZE_MENU );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_object_set_data( holder, "box3d_vp_x_state_action", act );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_x_state_changed), box3d_angle_x );
- gtk_action_set_sensitive( GTK_ACTION(box3d_angle_x), !prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_x_state", true) );
+ _freeze = true;
+ resync_toolbar(_repr);
+ _freeze = false;
+ }
}
+}
- /* Angle Y */
- {
- gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
- gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
- eact = create_adjustment_action( "3DBoxAngleYAction",
- _("Angle in Y direction"), _("Angle Y:"),
- // Translators: PL is short for 'perspective line'
- _("Angle of PLs in Y direction"),
- "/tools/shapes/3dbox/box3d_angle_y", 30,
- GTK_WIDGET(desktop->canvas), holder, FALSE, nullptr,
- -360.0, 360.0, 1.0, 10.0,
- labels, values, G_N_ELEMENTS(labels),
- box3d_angle_y_value_changed );
- gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
- g_object_set_data( holder, "box3d_angle_y_action", eact );
- box3d_angle_y = eact;
+void
+Box3DToolbar::resync_toolbar(Inkscape::XML::Node *persp_repr)
+{
+ if (!persp_repr) {
+ g_print ("No perspective given to box3d_resync_toolbar().\n");
+ return;
}
- if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Y)) {
- gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
- } else {
- gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
+ Persp3D *persp = persp3d_get_from_repr(persp_repr);
+ if (!persp) {
+ // Hmm, is it an error if this happens?
+ return;
}
+ set_button_and_adjustment(persp, Proj::X,
+ _angle_x_adj,
+ GTK_ACTION(_angle_x_action),
+ GTK_TOGGLE_ACTION(_vp_x_state_action));
+ set_button_and_adjustment(persp, Proj::Y,
+ _angle_y_adj,
+ GTK_ACTION(_angle_y_action),
+ GTK_TOGGLE_ACTION(_vp_y_state_action));
+ set_button_and_adjustment(persp, Proj::Z,
+ _angle_z_adj,
+ GTK_ACTION(_angle_z_action),
+ GTK_TOGGLE_ACTION(_vp_z_state_action));
+}
- /* VP Y state */
- {
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYStateAction",
- // Translators: VP is short for 'vanishing point'
- _("State of VP in Y direction"),
- _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
- INKSCAPE_ICON("perspective-parallel"),
- GTK_ICON_SIZE_MENU );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_object_set_data( holder, "box3d_vp_y_state_action", act );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_y_state_changed), box3d_angle_y );
- gtk_action_set_sensitive( GTK_ACTION(box3d_angle_y), !prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_y_state", true) );
- }
+void
+Box3DToolbar::set_button_and_adjustment(Persp3D *persp,
+ Proj::Axis axis,
+ Glib::RefPtr<Gtk::Adjustment>& adj,
+ GtkAction *act,
+ GtkToggleAction *tact)
+{
+ // TODO: Take all selected perspectives into account but don't touch the state button if not all of them
+ // have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states
+ // are reset).
+ bool is_infinite = !persp3d_VP_is_finite(persp->perspective_impl, axis);
- /* Angle Z */
- {
- gchar const* labels[] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
- gdouble values[] = {-90, -60, -30, 0, 30, 60, 90};
- eact = create_adjustment_action( "3DBoxAngleZAction",
- _("Angle in Z direction"), _("Angle Z:"),
- // Translators: PL is short for 'perspective line'
- _("Angle of PLs in Z direction"),
- "/tools/shapes/3dbox/box3d_angle_z", 30,
- GTK_WIDGET(desktop->canvas), holder, FALSE, nullptr,
- -360.0, 360.0, 1.0, 10.0,
- labels, values, G_N_ELEMENTS(labels),
- box3d_angle_z_value_changed );
- gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
- g_object_set_data( holder, "box3d_angle_z_action", eact );
- box3d_angle_z = eact;
- }
+ if (is_infinite) {
+ gtk_toggle_action_set_active(tact, TRUE);
+ gtk_action_set_sensitive(act, TRUE);
- if (!persp_impl || !persp3d_VP_is_finite(persp_impl, Proj::Z)) {
- gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ double angle = persp3d_get_infinite_angle(persp, axis);
+ if (angle != Geom::infinity()) { // FIXME: We should catch this error earlier (don't show the spinbutton at all)
+ adj->set_value(normalize_angle(angle));
+ }
} else {
- gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
+ gtk_toggle_action_set_active(tact, FALSE);
+ gtk_action_set_sensitive(act, FALSE);
}
+}
- /* VP Z state */
- {
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZStateAction",
- // Translators: VP is short for 'vanishing point'
- _("State of VP in Z direction"),
- _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
- INKSCAPE_ICON("perspective-parallel"),
- GTK_ICON_SIZE_MENU );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- g_object_set_data( holder, "box3d_vp_z_state_action", act );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_z_state_changed), box3d_angle_z );
- gtk_action_set_sensitive( GTK_ACTION(box3d_angle_z), !prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/shapes/3dbox/vp_z_state", true) );
+void
+Box3DToolbar::event_attr_changed(Inkscape::XML::Node *repr,
+ gchar const * /*name*/,
+ gchar const * /*old_value*/,
+ gchar const * /*new_value*/,
+ bool /*is_interactive*/,
+ gpointer data)
+{
+ auto toolbar = reinterpret_cast<Box3DToolbar*>(data);
+
+ // quit if run by the attr_changed or selection changed listener
+ if (toolbar->_freeze) {
+ return;
}
- desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_check_ec), holder));
- g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
+ // set freeze so that it can be caught in box3d_angle_z_value_changed() (to avoid calling
+ // SPDocumentUndo::maybeDone() when the document is undo insensitive)
+ toolbar->_freeze = true;
+
+ // TODO: Only update the appropriate part of the toolbar
+// if (!strcmp(name, "inkscape:vp_z")) {
+ toolbar->resync_toolbar(repr);
+// }
+
+ Persp3D *persp = persp3d_get_from_repr(repr);
+ persp3d_update_box_reprs(persp);
+
+ toolbar->_freeze = false;
}
-static void box3d_toolbox_check_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder)
-{
- static sigc::connection changed;
- if (SP_IS_BOX3D_CONTEXT(ec)) {
- changed = desktop->getSelection()->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), holder));
- box3d_toolbox_selection_changed(desktop->getSelection(), holder);
- } else {
- if (changed)
- changed.disconnect();
+/**
+ * \brief normalize angle so that it lies in the interval [0,360]
+ *
+ * TODO: Isn't there something in 2Geom or cmath that does this?
+ */
+double
+Box3DToolbar::normalize_angle(double a) {
+ double angle = a + ((int) (a/360.0))*360;
+ if (angle < 0) {
+ angle += 360.0;
}
+ return angle;
+}
+
+}
}
+}
+
/*
Local Variables: