X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fwidgets%2Fselect-toolbar.cpp;h=a0ec248ca5395ea313459d84852b72e8817e5d93;hb=5a43b2bbcb81ab7da396dad781d3f9b7854eb002;hp=6bcb24d2d34459934725b73d8dd41630a6266c4a;hpb=6129af7cc5b723223e9617614c931936e5190421;p=inkscape.git diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index 6bcb24d2d..a0ec248ca 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -4,6 +4,8 @@ * Authors: * Lauris Kaplinski * bulia byak + * Jon A. Cruz + * Abhishek Sharma * * Copyright (C) 2003-2005 authors * @@ -15,6 +17,7 @@ #endif #include +#include #include "widgets/button.h" #include "widgets/spw-utilities.h" @@ -23,7 +26,7 @@ #include "widgets/icon.h" #include "widgets/sp-widget.h" -#include "prefs-utils.h" +#include "preferences.h" #include "selection-chemistry.h" #include "document.h" #include "inkscape.h" @@ -37,62 +40,66 @@ #include "helper/units.h" #include "inkscape.h" #include "verbs.h" -#include "prefs-utils.h" #include "selection.h" #include "selection-chemistry.h" #include "sp-item-transform.h" #include "message-stack.h" +#include "display/sp-canvas.h" +#include "helper/unit-tracker.h" +#include "ege-adjustment-action.h" +#include "ege-output-action.h" +#include "ink-action.h" +#include <2geom/rect.h> +#include "ui/icon-names.h" +using Inkscape::UnitTracker; +using Inkscape::DocumentUndo; static void sp_selection_layout_widget_update(SPWidget *spw, Inkscape::Selection *sel) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); - GtkWidget *f = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(spw), "frame"); - - using NR::X; - using NR::Y; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + using Geom::X; + using Geom::Y; if ( sel && !sel->isEmpty() ) { - NR::Rect const bbox(sel->bounds()); - NR::Point const dimensions(bbox.dimensions()); - if ((dimensions[X] > 1e-6) || (dimensions[Y] > 1e-6)) { - GtkWidget *us = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(spw), "units"); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us)); + int prefs_bbox = prefs->getInt("/tools/bounding_box", 0); + SPItem::BBoxType bbox_type = (prefs_bbox ==0)? + SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + Geom::OptRect const bbox(sel->bounds(bbox_type)); + if ( bbox ) { + UnitTracker *tracker = reinterpret_cast(g_object_get_data(G_OBJECT(spw), "tracker")); + SPUnit const &unit = *tracker->getActiveUnit(); + + struct { char const *key; double val; } const keyval[] = { + { "X", bbox->min()[X] }, + { "Y", bbox->min()[Y] }, + { "width", bbox->dimensions()[X] }, + { "height", bbox->dimensions()[Y] } + }; if (unit.base == SP_UNIT_DIMENSIONLESS) { - char const * const keys[] = {"X", "Y", "width", "height"}; double const val = 1. / unit.unittobase; - for (unsigned i = 0; i < G_N_ELEMENTS(keys); ++i) { - GtkAdjustment *a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), keys[i]); + for (unsigned i = 0; i < G_N_ELEMENTS(keyval); ++i) { + GtkAdjustment *a = (GtkAdjustment *) g_object_get_data(G_OBJECT(spw), keyval[i].key); gtk_adjustment_set_value(a, val); + tracker->setFullVal( a, keyval[i].val ); } } else { - struct { char const *key; double val; } const keyval[] = { - { "X", bbox.min()[X] }, - { "Y", bbox.min()[Y] }, - { "width", dimensions[X] }, - { "height", dimensions[Y] } - }; for (unsigned i = 0; i < G_N_ELEMENTS(keyval); ++i) { - GtkAdjustment *a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), keyval[i].key); + GtkAdjustment *a = (GtkAdjustment *) g_object_get_data(G_OBJECT(spw), keyval[i].key); gtk_adjustment_set_value(a, sp_pixels_get_units(keyval[i].val, unit)); } } - - gtk_widget_set_sensitive(f, TRUE); - } else { - gtk_widget_set_sensitive(f, FALSE); } - } else { - gtk_widget_set_sensitive(f, FALSE); } - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } @@ -113,86 +120,101 @@ static void sp_selection_layout_widget_change_selection(SPWidget *spw, Inkscape::Selection *selection, gpointer data) { SPDesktop *desktop = (SPDesktop *) data; - if (sp_desktop_selection(desktop) == selection) // only respond to changes in our desktop + if (sp_desktop_selection(desktop) == selection) { // only respond to changes in our desktop + gboolean setActive = (selection && !selection->isEmpty()); + std::vector *contextActions = reinterpret_cast *>(g_object_get_data(G_OBJECT(spw), "contextActions")); + if ( contextActions ) { + for ( std::vector::iterator iter = contextActions->begin(); + iter != contextActions->end(); ++iter) { + if ( setActive != gtk_action_is_sensitive(*iter) ) { + gtk_action_set_sensitive( *iter, setActive ); + } + } + } + sp_selection_layout_widget_update(spw, selection); + } } static void sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) { - if (gtk_object_get_data(GTK_OBJECT(spw), "update")) { + if (g_object_get_data(G_OBJECT(spw), "update")) { return; } - GtkWidget *us = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(spw), "units"); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us)); - if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(us))) { + UnitTracker *tracker = reinterpret_cast(g_object_get_data(G_OBJECT(spw), "tracker")); + if ( !tracker || tracker->isUpdating() ) { /* * When only units are being changed, don't treat changes * to adjuster values as object changes. */ return; } - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *document = sp_desktop_document(desktop); - sp_document_ensure_up_to_date (document); - NR::Rect bbox = selection->bounds(); + document->ensureUpToDate (); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int prefs_bbox = prefs->getInt("/tools/bounding_box"); + SPItem::BBoxType bbox_type = (prefs_bbox ==0)? + SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; + Geom::OptRect bbox = selection->bounds(bbox_type); - if (!((bbox.max()[NR::X] - bbox.min()[NR::X] > 1e-6) || (bbox.max()[NR::Y] - bbox.min()[NR::Y] > 1e-6))) { + if ( !bbox ) { + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); return; } - gdouble x0, y0, x1, y1, xrel, yrel; - GtkAdjustment *a_w; - GtkAdjustment *a_h; + gdouble x0 = 0; + gdouble y0 = 0; + gdouble x1 = 0; + gdouble y1 = 0; + gdouble xrel = 0; + gdouble yrel = 0; + SPUnit const &unit = *tracker->getActiveUnit(); + + GtkAdjustment* a_x = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "X" ) ); + GtkAdjustment* a_y = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "Y" ) ); + GtkAdjustment* a_w = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "width" ) ); + GtkAdjustment* a_h = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "height" ) ); if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { - GtkAdjustment *a; - a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "X"); - x0 = sp_units_get_pixels (a->value, unit); - a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "Y"); - y0 = sp_units_get_pixels (a->value, unit); - a_w = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "width"); + x0 = sp_units_get_pixels (a_x->value, unit); + y0 = sp_units_get_pixels (a_y->value, unit); x1 = x0 + sp_units_get_pixels (a_w->value, unit); - xrel = sp_units_get_pixels (a_w->value, unit) / bbox.extent(NR::X); - a_h = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "height"); + xrel = sp_units_get_pixels (a_w->value, unit) / bbox->dimensions()[Geom::X]; y1 = y0 + sp_units_get_pixels (a_h->value, unit); - yrel = sp_units_get_pixels (a_h->value, unit) / bbox.extent(NR::Y); + yrel = sp_units_get_pixels (a_h->value, unit) / bbox->dimensions()[Geom::Y]; } else { - GtkAdjustment *a; - a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "X"); - double const x0_propn = a->value * unit.unittobase; - x0 = bbox.min()[NR::X] * x0_propn; - a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "Y"); - double const y0_propn = a->value * unit.unittobase; - y0 = y0_propn * bbox.min()[NR::Y]; - a_w = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "width"); + double const x0_propn = a_x->value * unit.unittobase; + x0 = bbox->min()[Geom::X] * x0_propn; + double const y0_propn = a_y->value * unit.unittobase; + y0 = y0_propn * bbox->min()[Geom::Y]; xrel = a_w->value * unit.unittobase; - x1 = x0 + xrel * bbox.extent(NR::X); - a_h = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "height"); + x1 = x0 + xrel * bbox->dimensions()[Geom::X]; yrel = a_h->value * unit.unittobase; - y1 = y0 + yrel * bbox.extent(NR::Y); + y1 = y0 + yrel * bbox->dimensions()[Geom::Y]; } // Keep proportions if lock is on - GtkWidget *lock = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(spw), "lock")); - if (SP_BUTTON_IS_DOWN(lock)) { + GtkToggleAction *lock = GTK_TOGGLE_ACTION( g_object_get_data(G_OBJECT(spw), "lock") ); + if ( gtk_toggle_action_get_active(lock) ) { if (adj == a_h) { - x1 = x0 + yrel * bbox.extent(NR::X); + x1 = x0 + yrel * bbox->dimensions()[Geom::X]; } else if (adj == a_w) { - y1 = y0 + xrel * bbox.extent(NR::Y); + y1 = y0 + xrel * bbox->dimensions()[Geom::Y]; } } // scales and moves, in px - double mh = fabs(x0 - bbox.min()[NR::X]); - double sh = fabs(x1 - bbox.max()[NR::X]); - double mv = fabs(y0 - bbox.min()[NR::Y]); - double sv = fabs(y1 - bbox.max()[NR::Y]); + double mh = fabs(x0 - bbox->min()[Geom::X]); + double sh = fabs(x1 - bbox->max()[Geom::X]); + double mv = fabs(y0 - bbox->min()[Geom::Y]); + double sv = fabs(y1 - bbox->max()[Geom::Y]); // unless the unit is %, convert the scales and moves to the unit if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) { @@ -207,269 +229,277 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) // the value was changed by the user, the difference will be at least that much; otherwise it's // just rounding difference between the spinbox value and actual value, so no action is // performed - char const * const actionkey = ( mh > 5e-4 ? "selector:toolbar:move:horizontal" : - sh > 5e-4 ? "selector:toolbar:scale:horizontal" : - mv > 5e-4 ? "selector:toolbar:move:vertical" : + char const * const actionkey = ( mh > 5e-4 ? "selector:toolbar:move:horizontal" : + sh > 5e-4 ? "selector:toolbar:scale:horizontal" : + mv > 5e-4 ? "selector:toolbar:move:vertical" : sv > 5e-4 ? "selector:toolbar:scale:vertical" : NULL ); if (actionkey != NULL) { + + // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); + gdouble strokewidth = stroke_average_width (selection->itemList()); - int transform_stroke = prefs_get_int_attribute ("options.transform", "stroke", 1); + int transform_stroke = prefs->getBool("/options/transform/stroke", true) ? 1 : 0; - NR::Matrix scaler = get_scale_transform_with_stroke (bbox, strokewidth, transform_stroke, x0, y0, x1, y1); + Geom::Matrix scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1); sp_selection_apply_affine(selection, scaler); - sp_document_maybe_done (document, actionkey); + DocumentUndo::maybeDone(document, actionkey, SP_VERB_CONTEXT_SELECT, + _("Transform by toolbar")); - // defocus spinbuttons by moving focus to the canvas, unless "stay" is on - spinbutton_defocus(GTK_OBJECT(spw)); + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); } - gtk_object_set_data(GTK_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); } -GtkWidget * -sp_select_toolbox_spinbutton(gchar *label, gchar *data, float lower_limit, GtkWidget *us, GtkWidget *spw, gchar *tooltip, gboolean altx) +static EgeAdjustmentAction * create_adjustment_action( gchar const *name, + gchar const *label, + gchar const *shortLabel, + gchar const *data, + gdouble lower, + GtkWidget* focusTarget, + UnitTracker* tracker, + GtkWidget* spw, + gchar const *tooltip, + gboolean altx ) { - GtkTooltips *tt = gtk_tooltips_new(); - - GtkWidget *hb = gtk_hbox_new(FALSE, 1); - GtkWidget *l = gtk_label_new(Q_(label)); - gtk_tooltips_set_tip(tt, l, tooltip, NULL); - gtk_widget_show(l); - gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); - gtk_container_add(GTK_CONTAINER(hb), l); - - GtkObject *a = gtk_adjustment_new(0.0, lower_limit, 1e6, SPIN_STEP, SPIN_PAGE_STEP, SPIN_PAGE_STEP); - sp_unit_selector_add_adjustment(SP_UNIT_SELECTOR(us), GTK_ADJUSTMENT(a)); - gtk_object_set_data(GTK_OBJECT(spw), data, a); - - GtkWidget *sb = gtk_spin_button_new(GTK_ADJUSTMENT(a), SPIN_STEP, 3); - gtk_tooltips_set_tip(tt, sb, tooltip, NULL); - gtk_widget_set_size_request(sb, AUX_SPINBUTTON_WIDTH, AUX_SPINBUTTON_HEIGHT); - gtk_widget_show(sb); - gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), spw); - gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), spw); - - gtk_container_add(GTK_CONTAINER(hb), sb); - gtk_signal_connect(GTK_OBJECT(a), "value_changed", GTK_SIGNAL_FUNC(sp_object_layout_any_value_changed), spw); - - if (altx) { // this spinbutton will be activated by alt-x - gtk_object_set_data(GTK_OBJECT(sb), "altx", sb); + GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( 0.0, lower, 1e6, SPIN_STEP, SPIN_PAGE_STEP, 0 ) ); + if (tracker) { + tracker->addAdjustment(adj); } - - return hb; -} - -static gboolean aux_set_unit(SPUnitSelector *, - SPUnit const *old, - SPUnit const *new_units, - GObject *dlg) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - - if (!desktop) { - return FALSE; + if ( spw ) { + g_object_set_data( G_OBJECT(spw), data, adj ); } - Inkscape::Selection *selection = sp_desktop_selection(desktop); - - if (selection->isEmpty()) - return FALSE; - - if ((old->base == SP_UNIT_ABSOLUTE || old->base == SP_UNIT_DEVICE) - && (new_units->base == SP_UNIT_DIMENSIONLESS)) - { - - /* Absolute to percentage */ - g_object_set_data(dlg, "update", GUINT_TO_POINTER(TRUE)); - - GtkAdjustment *ax = GTK_ADJUSTMENT(g_object_get_data(dlg, "X")); - GtkAdjustment *ay = GTK_ADJUSTMENT(g_object_get_data(dlg, "Y")); - GtkAdjustment *aw = GTK_ADJUSTMENT(g_object_get_data(dlg, "width")); - GtkAdjustment *ah = GTK_ADJUSTMENT(g_object_get_data(dlg, "height")); - - double const x = sp_units_get_pixels (ax->value, *old); - double const y = sp_units_get_pixels (ay->value, *old); - double const w = sp_units_get_pixels (aw->value, *old); - double const h = sp_units_get_pixels (ah->value, *old); - - NR::Rect bbox = selection->bounds(); - - gtk_adjustment_set_value(ax, fabs(bbox.min()[NR::X]) > 1e-6? 100.0 * x / bbox.min()[NR::X] : 100.0); - gtk_adjustment_set_value(ay, fabs(bbox.min()[NR::Y]) > 1e-6? 100.0 * y / bbox.min()[NR::Y] : 100.0); - gtk_adjustment_set_value(aw, fabs(bbox.extent(NR::X)) > 1e-6? 100.0 * w / bbox.extent(NR::X) : 100.0); - gtk_adjustment_set_value(ah, fabs(bbox.extent(NR::Y)) > 1e-6? 100.0 * h / bbox.extent(NR::Y) : 100.0); - - g_object_set_data(dlg, "update", GUINT_TO_POINTER(FALSE)); - return TRUE; - } else if ((old->base == SP_UNIT_DIMENSIONLESS) - && (new_units->base == SP_UNIT_ABSOLUTE || new_units->base == SP_UNIT_DEVICE)) { - - /* Percentage to absolute */ - g_object_set_data(dlg, "update", GUINT_TO_POINTER(TRUE)); - - GtkAdjustment *ax = GTK_ADJUSTMENT(g_object_get_data(dlg, "X")); - GtkAdjustment *ay = GTK_ADJUSTMENT(g_object_get_data(dlg, "Y")); - GtkAdjustment *aw = GTK_ADJUSTMENT(g_object_get_data(dlg, "width")); - GtkAdjustment *ah = GTK_ADJUSTMENT(g_object_get_data(dlg, "height")); - - NR::Rect bbox = selection->bounds(); + EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, Q_(label), tooltip, 0, SPIN_STEP, 3 ); + if ( shortLabel ) { + g_object_set( act, "short_label", Q_(shortLabel), NULL ); + } - gtk_adjustment_set_value(ax, sp_pixels_get_units(0.01 * ax->value * bbox.min()[NR::X], *new_units)); - gtk_adjustment_set_value(ay, sp_pixels_get_units(0.01 * ay->value * bbox.min()[NR::Y], *new_units)); - gtk_adjustment_set_value(aw, sp_pixels_get_units(0.01 * aw->value * bbox.extent(NR::X), *new_units)); - gtk_adjustment_set_value(ah, sp_pixels_get_units(0.01 * ah->value * bbox.extent(NR::Y), *new_units)); + gtk_signal_connect( GTK_OBJECT(adj), "value_changed", GTK_SIGNAL_FUNC(sp_object_layout_any_value_changed), spw ); + if ( focusTarget ) { + ege_adjustment_action_set_focuswidget( act, focusTarget ); + } - g_object_set_data(dlg, "update", GUINT_TO_POINTER(FALSE)); - return TRUE; + if ( altx ) { // this spinbutton will be activated by alt-x + g_object_set( G_OBJECT(act), "self-id", "altx", NULL ); } - return FALSE; + // Using a cast just to make sure we pass in the right kind of function pointer + g_object_set( G_OBJECT(act), "tool-post", static_cast(sp_set_font_size_smaller), NULL ); + + return act; } // toggle button callbacks and updaters -static void toggle_stroke (GtkWidget *button, gpointer data) { - prefs_set_int_attribute ("options.transform", "stroke", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0); +static void toggle_stroke( GtkToggleAction* act, gpointer data ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean active = gtk_toggle_action_get_active(act); + prefs->setBool("/options/transform/stroke", active); SPDesktop *desktop = (SPDesktop *)data; - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + if ( active ) { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now stroke width is scaled when objects are scaled.")); } else { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now stroke width is not scaled when objects are scaled.")); } } -static void toggle_corners (GtkWidget *button, gpointer data) { - prefs_set_int_attribute ("options.transform", "rectcorners", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0); +static void toggle_corners( GtkToggleAction* act, gpointer data) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean active = gtk_toggle_action_get_active(act); + prefs->setBool("/options/transform/rectcorners", active); SPDesktop *desktop = (SPDesktop *)data; - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + if ( active ) { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now rounded rectangle corners are scaled when rectangles are scaled.")); } else { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now rounded rectangle corners are not scaled when rectangles are scaled.")); } } -static void toggle_gradient (GtkWidget *button, gpointer data) { - prefs_set_int_attribute ("options.transform", "gradient", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0); +static void toggle_gradient( GtkToggleAction *act, gpointer data ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean active = gtk_toggle_action_get_active(act); + prefs->setBool("/options/transform/gradient", active); SPDesktop *desktop = (SPDesktop *)data; - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + if ( active ) { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now gradients are transformed along with their objects when those are transformed (moved, scaled, rotated, or skewed).")); } else { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now gradients remain fixed when objects are transformed (moved, scaled, rotated, or skewed).")); } } -static void toggle_pattern (GtkWidget *button, gpointer data) { - prefs_set_int_attribute ("options.transform", "pattern", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 1 : 0); +static void toggle_pattern( GtkToggleAction* act, gpointer data ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean active = gtk_toggle_action_get_active(act); + prefs->setInt("/options/transform/pattern", active); SPDesktop *desktop = (SPDesktop *)data; - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { + if ( active ) { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now patterns are transformed along with their objects when those are transformed (moved, scaled, rotated, or skewed).")); } else { desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Now patterns remain fixed when objects are transformed (moved, scaled, rotated, or skewed).")); } } -static void toggle_lock (GtkWidget *button, gpointer data) { +static void toggle_lock( GtkToggleAction *act, gpointer /*data*/ ) { + gboolean active = gtk_toggle_action_get_active( act ); + if ( active ) { + g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON_OBJECT_LOCKED, NULL ); + } else { + g_object_set( G_OBJECT(act), "iconId", INKSCAPE_ICON_OBJECT_UNLOCKED, NULL ); + } +} - GtkWidget *old_child = gtk_bin_get_child(GTK_BIN(button)); - gtk_container_remove (GTK_CONTAINER(button), old_child); +static void destroy_tracker( GObject* obj, gpointer /*user_data*/ ) +{ + UnitTracker *tracker = reinterpret_cast(g_object_get_data(obj, "tracker")); + if ( tracker ) { + delete tracker; + g_object_set_data( obj, "tracker", 0 ); + } +} - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { - GtkWidget *child = sp_icon_new (Inkscape::ICON_SIZE_DECORATION, "width_height_lock"); - gtk_widget_show (child); - gtk_container_add (GTK_CONTAINER (button), child); - } else { - GtkWidget *child = sp_icon_new (Inkscape::ICON_SIZE_DECORATION, "lock_unlocked"); - gtk_widget_show (child); - gtk_container_add (GTK_CONTAINER (button), child); +static void trigger_sp_action( GtkAction* /*act*/, gpointer user_data ) +{ + SPAction* targetAction = SP_ACTION(user_data); + if ( targetAction ) { + sp_action_perform( targetAction, NULL ); } } -GtkWidget * -sp_select_toolbox_new(SPDesktop *desktop) +static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::View::View* view, Inkscape::IconSize size ) { - Inkscape::UI::View::View *view = desktop; + GtkAction* act = 0; + + SPAction* targetAction = verb->get_action(view); + InkAction* inky = ink_action_new( verb->get_id(), verb->get_name(), verb->get_tip(), verb->get_image(), size ); + act = GTK_ACTION(inky); - GtkTooltips *tt = gtk_tooltips_new(); - GtkWidget *tb = gtk_hbox_new(FALSE, 0); + g_signal_connect( G_OBJECT(inky), "activate", GTK_SIGNAL_FUNC(trigger_sp_action), targetAction ); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_ROTATE_90_CCW), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_ROTATE_90_CW), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_FLIP_HORIZONTAL), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_OBJECT_FLIP_VERTICAL), view, tt); + Inkscape::queueIconPrerender( verb->get_image(), size ); - aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS); + return act; +} - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_TO_BACK), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_LOWER), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_RAISE), view, tt); - sp_toolbox_button_normal_new_from_verb(tb, Inkscape::ICON_SIZE_SMALL_TOOLBAR, Inkscape::Verb::get(SP_VERB_SELECTION_TO_FRONT), view, tt); +void sp_select_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) +{ + Inkscape::UI::View::View *view = desktop; + Inkscape::IconSize secondarySize = Inkscape::UI::ToolboxFactory::prefToSize("/toolbox/secondary", 1); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + GtkAction* act = 0; + + GtkActionGroup* selectionActions = mainActions; // temporary + std::vector* contextActions = new std::vector(); + + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_EDIT_SELECT_ALL), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_EDIT_DESELECT), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_OBJECT_ROTATE_90_CCW), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_OBJECT_ROTATE_90_CW), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_OBJECT_FLIP_HORIZONTAL), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_OBJECT_FLIP_VERTICAL), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_SELECTION_TO_BACK), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_SELECTION_LOWER), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_SELECTION_RAISE), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); + act = create_action_for_verb( Inkscape::Verb::get(SP_VERB_SELECTION_TO_FRONT), view, secondarySize ); + gtk_action_group_add_action( selectionActions, act ); + contextActions->push_back( act ); // Create the parent widget for x y w h tracker. GtkWidget *spw = sp_widget_new_global(INKSCAPE); // Remember the desktop's canvas widget, to be used for defocusing. - gtk_object_set_data(GTK_OBJECT(spw), "dtw", sp_desktop_canvas(desktop)); + g_object_set_data(G_OBJECT(spw), "dtw", sp_desktop_canvas(desktop)); // The vb frame holds all other widgets and is used to set sensitivity depending on selection state. GtkWidget *vb = gtk_hbox_new(FALSE, 0); gtk_widget_show(vb); gtk_container_add(GTK_CONTAINER(spw), vb); - gtk_object_set_data(GTK_OBJECT(spw), "frame", vb); // Create the units menu. - GtkWidget *us = sp_unit_selector_new(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE); - sp_unit_selector_setsize(us, AUX_OPTION_MENU_WIDTH, AUX_OPTION_MENU_HEIGHT); - sp_unit_selector_add_unit(SP_UNIT_SELECTOR(us), &sp_unit_get_by_id(SP_UNIT_PERCENT), 0); - sp_unit_selector_set_unit (SP_UNIT_SELECTOR(us), sp_desktop_namedview(desktop)->doc_units); - g_signal_connect(G_OBJECT(us), "set_unit", G_CALLBACK(aux_set_unit), spw); + UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE ); + tracker->addUnit( SP_UNIT_PERCENT, 0 ); + tracker->setActiveUnit( sp_desktop_namedview(desktop)->doc_units ); + + g_object_set_data( G_OBJECT(spw), "tracker", tracker ); + g_signal_connect( G_OBJECT(spw), "destroy", G_CALLBACK(destroy_tracker), spw ); + + EgeAdjustmentAction* eact = 0; // four spinbuttons - gtk_container_add(GTK_CONTAINER(vb), - //TRANSLATORS: only translate "string" in "context|string". - // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS - sp_select_toolbox_spinbutton(_("select_toolbar|X"), "X", -1e6, us, spw, _("Horizontal coordinate of selection"), TRUE)); - aux_toolbox_space(vb, AUX_BETWEEN_SPINBUTTONS); - gtk_container_add(GTK_CONTAINER(vb), - //TRANSLATORS: only translate "string" in "context|string". - // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS - sp_select_toolbox_spinbutton(_("select_toolbar|Y"), "Y", -1e6, us, spw, _("Vertical coordinate of selection"), FALSE)); - aux_toolbox_space(vb, AUX_BETWEEN_BUTTON_GROUPS); - - gtk_container_add(GTK_CONTAINER(vb), - //TRANSLATORS: only translate "string" in "context|string". - // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS - sp_select_toolbox_spinbutton(_("select_toolbar|W"), "width", 1e-3, us, spw, _("Width of selection"), FALSE)); + eact = create_adjustment_action( "XAction", C_("Select toolbar", "X position"), C_("Select toolbar", "X:"), "X", + -1e6, GTK_WIDGET(desktop->canvas), tracker, spw, + _("Horizontal coordinate of selection"), TRUE ); + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); + contextActions->push_back( GTK_ACTION(eact) ); + + eact = create_adjustment_action( "YAction", C_("Select toolbar", "Y position"), C_("Select toolbar", "Y:"), "Y", + -1e6, GTK_WIDGET(desktop->canvas), tracker, spw, + _("Vertical coordinate of selection"), FALSE ); + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); + contextActions->push_back( GTK_ACTION(eact) ); + + eact = create_adjustment_action( "WidthAction", C_("Select toolbar", "Width"), C_("Select toolbar", "W:"), "width", + 1e-3, GTK_WIDGET(desktop->canvas), tracker, spw, + _("Width of selection"), FALSE ); + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); + contextActions->push_back( GTK_ACTION(eact) ); // lock toggle - GtkWidget *lockbox = gtk_vbox_new(TRUE, 0); - GtkWidget *lock = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - "lock_unlocked", - _("When locked, change both width and height by the same proportion"), - tt); - gtk_box_pack_start(GTK_BOX(lockbox), lock, TRUE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vb), lockbox, FALSE, FALSE, 0); - gtk_object_set_data(GTK_OBJECT(spw), "lock", lock); - g_signal_connect_after (G_OBJECT (lock), "clicked", G_CALLBACK (toggle_lock), desktop); - - gtk_container_add(GTK_CONTAINER(vb), - //TRANSLATORS: only translate "string" in "context|string". - // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS - sp_select_toolbox_spinbutton(_("select_toolbar|H"), "height", 1e-3, us, spw, _("Height of selection"), FALSE)); - - aux_toolbox_space(vb, 2); + { + InkToggleAction* itact = ink_toggle_action_new( "LockAction", + _("Lock width and height"), + _("When locked, change both width and height by the same proportion"), + INKSCAPE_ICON_OBJECT_UNLOCKED, + Inkscape::ICON_SIZE_DECORATION ); + g_object_set( itact, "short_label", "Lock", NULL ); + g_object_set_data( G_OBJECT(spw), "lock", itact ); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(toggle_lock), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); + } + + eact = create_adjustment_action( "HeightAction", C_("Select toolbar", "Height"), C_("Select toolbar", "H:"), "height", + 1e-3, GTK_WIDGET(desktop->canvas), tracker, spw, + _("Height of selection"), FALSE ); + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); + contextActions->push_back( GTK_ACTION(eact) ); // Add the units menu. - gtk_widget_show(us); - gtk_container_add(GTK_CONTAINER(vb), us); - gtk_object_set_data(GTK_OBJECT(spw), "units", us); + act = tracker->createAction( "UnitsAction", _("Units"), ("") ); + gtk_action_group_add_action( selectionActions, act ); - // Set font size. - sp_set_font_size_smaller (vb); + g_object_set_data( G_OBJECT(spw), "selectionActions", selectionActions ); + g_object_set_data( G_OBJECT(spw), "contextActions", contextActions ); // Force update when selection changes. gtk_signal_connect(GTK_OBJECT(spw), "modify_selection", GTK_SIGNAL_FUNC(sp_selection_layout_widget_modify_selection), desktop); @@ -478,70 +508,74 @@ sp_select_toolbox_new(SPDesktop *desktop) // Update now. sp_selection_layout_widget_update(SP_WIDGET(spw), SP_ACTIVE_DESKTOP ? sp_desktop_selection(SP_ACTIVE_DESKTOP) : NULL); - // Insert spw into the toolbar. - gtk_box_pack_start(GTK_BOX(tb), spw, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS); + for ( std::vector::iterator iter = contextActions->begin(); + iter != contextActions->end(); ++iter) { + if ( gtk_action_is_sensitive(*iter) ) { + gtk_action_set_sensitive( *iter, FALSE ); + } + } - aux_toolbox_space(tb, AUX_BETWEEN_BUTTON_GROUPS); + // Insert spw into the toolbar. + if ( GTK_IS_BOX(holder) ) { + gtk_box_pack_start(GTK_BOX(holder), spw, FALSE, FALSE, 0); + } else if ( GTK_IS_TOOLBAR(holder) ) { + gtk_toolbar_append_widget( GTK_TOOLBAR(holder), spw, "Text", "priv" ); + } else { + g_warning("Unexpected holder type"); + } // "Transform with object" buttons - GtkWidget *cvbox = gtk_vbox_new (FALSE, 0); - GtkWidget *cbox = gtk_hbox_new (FALSE, 0); - { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - "transform_stroke", - _("When scaling objects, scale the stroke width by the same proportion"), - tt); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("options.transform", "stroke", 1)); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_stroke), desktop); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); + EgeOutputAction* act = ege_output_action_new( "transform_affect_label", _("Affect:"), _("Control whether or not to scale stroke widths, scale rectangle corners, transform gradient fills, and transform pattern fills with the object"), 0 ); + ege_output_action_set_use_markup( act, TRUE ); + g_object_set( act, "visible-overflown", FALSE, NULL ); + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); } { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - "transform_corners", - _("When scaling rectangles, scale the radii of rounded corners"), - tt); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("options.transform", "rectcorners", 1)); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_corners), desktop); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); + InkToggleAction* itact = ink_toggle_action_new( "transform_stroke", + _("Scale stroke width"), + _("When scaling objects, scale the stroke width by the same proportion"), + INKSCAPE_ICON_TRANSFORM_AFFECT_STROKE, + Inkscape::ICON_SIZE_DECORATION ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), prefs->getBool("/options/transform/stroke", true) ); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(toggle_stroke), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); } { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - "transform_gradient", - _("Transform gradients (in fill or stroke) along with the objects"), - tt); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("options.transform", "gradient", 1)); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_gradient), desktop); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); + InkToggleAction* itact = ink_toggle_action_new( "transform_corners", + _("Scale rounded corners"), + _("When scaling rectangles, scale the radii of rounded corners"), + INKSCAPE_ICON_TRANSFORM_AFFECT_ROUNDED_CORNERS, + Inkscape::ICON_SIZE_DECORATION ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), prefs->getBool("/options/transform/rectcorners", true) ); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(toggle_corners), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); } { - GtkWidget *button = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, - SP_BUTTON_TYPE_TOGGLE, - NULL, - "transform_pattern", - _("Transform patterns (in fill or stroke) along with the objects"), - tt); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), prefs_get_int_attribute ("options.transform", "pattern", 1)); - g_signal_connect_after (G_OBJECT (button), "clicked", G_CALLBACK (toggle_pattern), desktop); - gtk_box_pack_start(GTK_BOX(cbox), button, FALSE, FALSE, 0); + InkToggleAction* itact = ink_toggle_action_new( "transform_gradient", + _("Move gradients"), + _("Move gradients (in fill or stroke) along with the objects"), + INKSCAPE_ICON_TRANSFORM_AFFECT_GRADIENT, + Inkscape::ICON_SIZE_DECORATION ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), prefs->getBool("/options/transform/gradient", true) ); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(toggle_gradient), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); } - gtk_box_pack_start(GTK_BOX(cvbox), cbox, TRUE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tb), cvbox, FALSE, FALSE, 0); - - gtk_widget_show_all(tb); - - return tb; + { + InkToggleAction* itact = ink_toggle_action_new( "transform_pattern", + _("Move patterns"), + _("Move patterns (in fill or stroke) along with the objects"), + INKSCAPE_ICON_TRANSFORM_AFFECT_PATTERN, + Inkscape::ICON_SIZE_DECORATION ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(itact), prefs->getBool("/options/transform/pattern", true) ); + g_signal_connect_after( G_OBJECT(itact), "toggled", G_CALLBACK(toggle_pattern), desktop) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); + } }