index d92e7e7a64db4a3c0659986e93821b1764dd045a..fcf3e0ce6bd874917ee2b0730179a33b326adf6e 100644 (file)
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
# include "config.h"
#endif
+#include <cstring>
+#include <string>
+
#include <gtkmm.h>
#include <gtk/gtk.h>
#include <iostream>
#include "widgets/spw-utilities.h"
#include "widgets/spinbutton-events.h"
#include "dialogs/text-edit.h"
+#include "dialogs/dialog-events.h"
#include "ui/widget/style-swatch.h"
#include "document-private.h"
#include "desktop-style.h"
#include "../libnrtype/font-lister.h"
+#include "../libnrtype/font-instance.h"
#include "../connection-pool.h"
#include "../prefs-utils.h"
#include "../inkscape-stock.h"
#include "ege-select-one-action.h"
#include "helper/unit-tracker.h"
+#include "svg/css-ostringstream.h"
+
using Inkscape::UnitTracker;
typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
static void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_arc_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
-static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
+static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
static void sp_pen_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder);
{ "SPTweakContext", "tweak_tool", SP_VERB_CONTEXT_TWEAK, SP_VERB_CONTEXT_TWEAK_PREFS },
{ "SPZoomContext", "zoom_tool", SP_VERB_CONTEXT_ZOOM, SP_VERB_CONTEXT_ZOOM_PREFS },
{ "SPRectContext", "rect_tool", SP_VERB_CONTEXT_RECT, SP_VERB_CONTEXT_RECT_PREFS },
-// { "SP3DBoxContext", "3dbox_tool", SP_VERB_CONTEXT_3DBOX, SP_VERB_CONTEXT_3DBOX_PREFS },
+ { "Box3DContext", "3dbox_tool", SP_VERB_CONTEXT_3DBOX, SP_VERB_CONTEXT_3DBOX_PREFS },
{ "SPArcContext", "arc_tool", SP_VERB_CONTEXT_ARC, SP_VERB_CONTEXT_ARC_PREFS },
{ "SPStarContext", "star_tool", SP_VERB_CONTEXT_STAR, SP_VERB_CONTEXT_STAR_PREFS },
{ "SPSpiralContext", "spiral_tool", SP_VERB_CONTEXT_SPIRAL, SP_VERB_CONTEXT_SPIRAL_PREFS },
SP_VERB_CONTEXT_STAR_PREFS, "tools.shapes.star", _("Style of new stars")},
{ "SPRectContext", "rect_toolbox", 0, sp_rect_toolbox_prep, "RectToolbar",
SP_VERB_CONTEXT_RECT_PREFS, "tools.shapes.rect", _("Style of new rectangles")},
- { "SP3DBoxContext", "3dbox_toolbox", 0, sp_3dbox_toolbox_prep, "3DBoxToolbar",
+ { "Box3DContext", "3dbox_toolbox", 0, box3d_toolbox_prep, "3DBoxToolbar",
SP_VERB_CONTEXT_3DBOX_PREFS, "tools.shapes.3dbox", _("Style of new 3D boxes")},
{ "SPArcContext", "arc_toolbox", 0, sp_arc_toolbox_prep, "ArcToolbar",
SP_VERB_CONTEXT_ARC_PREFS, "tools.shapes.arc", _("Style of new ellipses")},
" <toolitem action='StrokeToPath' />"
" <separator />"
" <toolitem action='NodesShowHandlesAction' />"
+ " <toolitem action='NodesShowHelperpath' />"
" <separator />"
" <toolitem action='EditNextLPEParameterAction' />"
" <separator />"
" </toolbar>"
" <toolbar name='3DBoxToolbar'>"
- " <toolitem action='3DBoxPosAngleXAction' />"
- " <toolitem action='3DBoxVPXAction' />"
- " <separator />"
- " <toolitem action='3DBoxPosAngleYAction' />"
- " <toolitem action='3DBoxVPYAction' />"
+ " <toolitem action='3DBoxAngleXAction' />"
+ " <toolitem action='3DBoxVPXStateAction' />"
" <separator />"
- " <toolitem action='3DBoxPosAngleZAction' />"
- " <toolitem action='3DBoxVPZAction' />"
+ " <toolitem action='3DBoxAngleYAction' />"
+ " <toolitem action='3DBoxVPYStateAction' />"
" <separator />"
+ " <toolitem action='3DBoxAngleZAction' />"
+ " <toolitem action='3DBoxVPZStateAction' />"
" </toolbar>"
" <toolbar name='SpiralToolbar'>"
@@ -501,7 +508,7 @@ static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::Vi
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 );
+ InkAction* inky = ink_action_new( verb->get_id(), _(verb->get_name()), verb->get_tip(), verb->get_image(), size );
act = GTK_ACTION(inky);
gtk_action_set_sensitive( act, targetAction->sensitive );
{
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
- GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
- GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
- gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
- gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
g_object_set_data(G_OBJECT(tb), "desktop", NULL);
- g_object_set_data(G_OBJECT(tb), "top_spacer", tb_s);
gtk_widget_set_sensitive(tb, FALSE);
{
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
- GtkWidget *tb_s = gtk_vbox_new(FALSE, 0);
- GtkWidget *tb_e = gtk_vbox_new(FALSE, 0);
gtk_box_set_spacing(GTK_BOX(tb), AUX_SPACING);
- gtk_box_pack_start(GTK_BOX(tb), GTK_WIDGET(tb_s), FALSE, FALSE, 0);
- gtk_box_pack_end(GTK_BOX(tb), GTK_WIDGET(tb_e), FALSE, FALSE, 0);
g_object_set_data(G_OBJECT(tb), "desktop", NULL);
gtk_widget_set_sensitive(tb, FALSE);
if (shape_editor) shape_editor->show_handles(show);
}
+static void toggle_show_helperpath (GtkToggleAction *act, gpointer /*data*/) {
+ bool show = gtk_toggle_action_get_active( act );
+ prefs_set_int_attribute ("tools.nodes", "show_helperpath", show ? 1 : 0);
+ ShapeEditor *shape_editor = get_current_shape_editor();
+ if (shape_editor) shape_editor->show_helperpath(show);
+}
+
void sp_node_path_edit_nextLPEparam (GtkAction */*act*/, gpointer data) {
sp_selection_next_patheffect_param( reinterpret_cast<SPDesktop*>(data) );
}
@@ -1098,6 +1103,17 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.nodes", "show_handles", 1 ) );
}
+ {
+ InkToggleAction* act = ink_toggle_action_new( "NodesShowHelperpath",
+ _("Show Outline"),
+ _("Show the outline of the path"),
+ "nodes_show_helperpath",
+ Inkscape::ICON_SIZE_DECORATION );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(toggle_show_helperpath), desktop );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.nodes", "show_helperpath", 0 ) );
+ }
+
{
InkAction* inky = ink_action_new( "EditNextLPEParameterAction",
_("Next Path Effect Parameter"),
}
gtk_widget_show(toolbox);
- // need to show the spacer, or the padding will be off
- GtkWidget *spacer = GTK_WIDGET(g_object_get_data(G_OBJECT(toolbox), "top_spacer"));
- gtk_widget_show(spacer);
-
gtk_widget_show_all(shown_toolbox);
}
@@ -1725,6 +1737,9 @@ static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *n
GtkAdjustment *adj = 0;
+ gchar const *flatsidedstr = prefs_get_string_attribute( "tools.shapes.star", "isflatsided" );
+ bool isFlatSided = flatsidedstr ? (strcmp(flatsidedstr, "false") != 0) : true;
+
if (!strcmp(name, "inkscape:randomized")) {
adj = GTK_ADJUSTMENT( gtk_object_get_data(GTK_OBJECT(tbl), "randomized") );
gtk_adjustment_set_value(adj, sp_repr_get_double_attribute(repr, "inkscape:randomized", 0.0));
@@ -1742,7 +1757,7 @@ static void star_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *n
ege_select_one_action_set_active( flat_action, 0 );
gtk_action_set_sensitive( prop_action, FALSE );
}
- } else if (!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) {
+ } else if ((!strcmp(name, "sodipodi:r1") || !strcmp(name, "sodipodi:r2")) && (!isFlatSided) ) {
adj = (GtkAdjustment*)gtk_object_get_data(GTK_OBJECT(tbl), "proportion");
gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0);
gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0);
@@ -1873,7 +1888,6 @@ static void sp_star_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
}
{
- //EgeAdjustmentAction* calligraphy_angle = 0;
EgeAdjustmentAction* eact = 0;
gchar const *flatsidedstr = prefs_get_string_attribute( "tools.shapes.star", "isflatsided" );
bool isFlatSided = flatsidedstr ? (strcmp(flatsidedstr, "false") != 0) : true;
@@ -2343,277 +2357,356 @@ static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
//## 3D Box ##
//########################
-static void sp_3dbox_toggle_vp_changed (GtkToggleAction */*act*/, GObject *dataKludge, Box3D::Axis axis)
-{
- SPDesktop *desktop = (SPDesktop *) g_object_get_data (dataKludge, "desktop");
- SPDocument *document = sp_desktop_document (desktop);
- Box3D::Perspective3D *persp = document->current_perspective;
+// 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, 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 != NR_HUGE) { // 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);
+ }
+}
- g_return_if_fail (is_single_axis_direction (axis));
- g_return_if_fail (persp);
+static void
+box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) {
+ if (!persp_repr) {
+ g_print ("No perspective given to box3d_resync_toolbar().\n");
+ return;
+ }
- persp->toggle_boxes (axis);
+ GtkWidget *tbl = GTK_WIDGET(data);
+ GtkAdjustment *adj = 0;
+ GtkAction *act = 0;
+ GtkToggleAction *tact = 0;
+ Persp3D *persp = persp3d_get_from_repr(persp_repr);
+ {
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_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;
- gchar *str;
- switch (axis) {
- case Box3D::X:
- str = g_strdup ("box3d_angle_x_action");
- break;
- case Box3D::Y:
- str = g_strdup ("box3d_angle_y_action");
- break;
- case Box3D::Z:
- str = g_strdup ("box3d_angle_z_action");
- break;
- default:
- return;
+ box3d_set_button_and_adjustment(persp, Proj::X, adj, act, tact);
}
- GtkAction* angle_action = GTK_ACTION (g_object_get_data (dataKludge, str));
- if (angle_action) {
- gtk_action_set_sensitive (angle_action, !persp->get_vanishing_point (axis)->is_finite() );
+ {
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_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);
}
+ {
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_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;
- // FIXME: Given how it is realized in the other tools, this is probably not the right way to do it,
- // but without the if construct, we get continuous segfaults. Needs further investigation.
- if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
- sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX,
- _("3D Box: Change perspective"));
+ box3d_set_button_and_adjustment(persp, Proj::Z, adj, act, tact);
}
}
-static void sp_3dbox_toggle_vp_x_changed(GtkToggleAction *act, GObject *dataKludge)
+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)
{
- sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::X);
-}
+ GtkWidget *tbl = GTK_WIDGET(data);
-static void sp_3dbox_toggle_vp_y_changed(GtkToggleAction *act, GObject *dataKludge)
-{
- sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Y);
+ // quit if run by the attr_changed listener
+ // note: it used to work without the differently called freeze_ attributes (here and in
+ // box3d_angle_value_changed()) but I now it doesn't so I'm leaving them in for now
+ if (g_object_get_data(G_OBJECT(tbl), "freeze_angle")) {
+ return;
+ }
+
+ // set freeze so that it can be caught in box3d_angle_z_value_changed() (to avoid calling
+ // sp_document_maybe_done() when the document is undo insensitive)
+ g_object_set_data(G_OBJECT(tbl), "freeze_attr", 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);
+
+ g_object_set_data(G_OBJECT(tbl), "freeze_attr", GINT_TO_POINTER(FALSE));
}
-static void sp_3dbox_toggle_vp_z_changed(GtkToggleAction *act, GObject *dataKludge)
+static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events =
{
- sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Z);
-}
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ box3d_persp_tb_event_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
-static void sp_3dbox_vp_angle_changed(GtkAdjustment *adj, GObject *dataKludge, Box3D::Axis axis )
+/**
+ * \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)
{
- SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop");
- Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective;
+ // 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).
- if (persp) {
- double angle = adj->value * M_PI/180;
- persp->set_infinite_direction (axis, NR::Point (cos (angle), sin (angle)));
+ Inkscape::XML::Node *persp_repr = NULL;
+ purge_repr_listener(tbl, tbl);
- // FIXME: See comment above; without the if construct we get segfaults during undo.
- if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
- sp_document_maybe_done(sp_desktop_document(desktop), "perspectiveangle", SP_VERB_CONTEXT_3DBOX,
- _("3D Box: Change perspective"));
+ SPItem *item = selection->singleItem();
+ if (item && SP_IS_BOX3D(item)) {
+ // FIXME: Also deal with multiple selected boxes
+ SPBox3D *box = SP_BOX3D(item);
+ Persp3D *persp = box3d_get_perspective(box);
+ persp_repr = SP_OBJECT_REPR(persp);
+ 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);
}
+
+ inkscape_active_document()->current_persp3d = persp3d_get_from_repr(persp_repr);
+ prefs_set_string_attribute("tools.shapes.3dbox", "persp", persp_repr->attribute("id"));
+
+ box3d_resync_toolbar(persp_repr, tbl);
}
- //g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
}
-static void sp_3dbox_vpx_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+static void
+box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis)
{
- sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::X);
+ SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
+ SPDocument *document = sp_desktop_document(desktop);
+
+ // quit if run by the attr_changed listener
+ // note: it used to work without the differently called freeze_ attributes (here and in
+ // box3d_persp_tb_event_attr_changed()) but I now it doesn't so I'm leaving them in for now
+ if (g_object_get_data( dataKludge, "freeze_attr" )) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ g_object_set_data(dataKludge, "freeze_angle", GINT_TO_POINTER(TRUE));
+
+ //Persp3D *persp = document->current_persp3d;
+ std::set<Persp3D *> sel_persps = persp3d_currently_selected_persps (inkscape_active_event_context());
+ if (sel_persps.empty()) {
+ // this can happen when the document is created; we silently ignore it
+ return;
+ }
+ Persp3D *persp = *(sel_persps.begin());
+
+ persp->tmat.set_infinite_direction (axis, adj->value);
+ SP_OBJECT(persp)->updateRepr();
+
+ // TODO: use the correct axis here, too
+ sp_document_maybe_done(document, "perspangle", SP_VERB_CONTEXT_3DBOX, _("3D Box: Change perspective (angle of infinite axis)"));
+
+ g_object_set_data( dataKludge, "freeze_angle", GINT_TO_POINTER(FALSE) );
}
-static void sp_3dbox_vpy_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+
+static void
+box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge)
{
- sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Y);
+ box3d_angle_value_changed(adj, dataKludge, Proj::X);
}
-static void sp_3dbox_vpz_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+static void
+box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge)
{
- sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Z);
+ box3d_angle_value_changed(adj, dataKludge, Proj::Y);
}
-// normalize angle so that it lies in the interval [0,360]
-static double sp_3dbox_normalize_angle (double a) {
- double angle = a + ((int) (a/360.0))*360;
- if (angle < 0) {
- angle += 360.0;
- }
- return angle;
+static void
+box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge)
+{
+ box3d_angle_value_changed(adj, dataKludge, Proj::Z);
}
-static void sp_3dbox_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);
- // FIXME: if we check for "freeze" as in other tools, no action is performed at all ...
- /***
- // quit if run by the _changed callbacks
- if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction *box3d_angle, Proj::Axis axis )
+{
+ // TODO: Take all selected perspectives into account
+ std::set<Persp3D *> sel_persps = persp3d_currently_selected_persps (inkscape_active_event_context());
+ if (sel_persps.empty()) {
+ // this can happen when the document is created; we silently ignore it
return;
}
+ Persp3D *persp = *(sel_persps.begin());
- // in turn, prevent callbacks from responding
- g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
- ***/
-
- if (!strcmp(name, "inkscape:perspective")) {
- GtkAdjustment *adj = 0;
- double angle;
- SPDesktop *desktop = (SPDesktop *) g_object_get_data(G_OBJECT(tbl), "desktop");
- Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective;
-
- adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_x"));
- angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::X)->get_angle());
- gtk_adjustment_set_value(adj, angle);
-
- adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_y"));
- angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Y)->get_angle());
- gtk_adjustment_set_value(adj, angle);
-
- adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_z"));
- angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Z)->get_angle());
- gtk_adjustment_set_value(adj, angle);
- }
+ bool set_infinite = gtk_toggle_action_get_active(act);
+ persp3d_set_VP_state (persp, axis, set_infinite ? Proj::VP_INFINITE : Proj::VP_FINITE);
}
-static Inkscape::XML::NodeEventVector sp_3dbox_tb_repr_events =
+static void box3d_vp_x_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
{
- NULL, /* child_added */
- NULL, /* child_removed */
- sp_3dbox_tb_event_attr_changed,
- NULL, /* content_changed */
- NULL /* order_changed */
-};
+ box3d_vp_state_changed(act, box3d_angle, Proj::X);
+}
-/**
- * \param selection Should not be NULL.
- */
-static void
-sp_3dbox_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
+static void box3d_vp_y_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
{
- Inkscape::XML::Node *repr = NULL;
- purge_repr_listener(tbl, tbl);
+ box3d_vp_state_changed(act, box3d_angle, Proj::Y);
+}
- SPItem *item = selection->singleItem();
- if (item) {
- repr = SP_OBJECT_REPR(item);
- if (repr) {
- g_object_set_data(tbl, "repr", repr);
- Inkscape::GC::anchor(repr);
- sp_repr_add_listener(repr, &sp_3dbox_tb_repr_events, tbl);
- sp_repr_synthesize_events(repr, &sp_3dbox_tb_repr_events, tbl);
- }
- }
+static void box3d_vp_z_state_changed( GtkToggleAction *act, GtkAction *box3d_angle )
+{
+ box3d_vp_state_changed(act, box3d_angle, Proj::Z);
}
-static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
+static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
EgeAdjustmentAction* eact = 0;
SPDocument *document = sp_desktop_document (desktop);
- Box3D::Perspective3D *persp = document->current_perspective;
- bool toggled = false;
-
- /* angle of VP in X direction */
- eact = create_adjustment_action("3DBoxPosAngleXAction",
- _("Angle X"), _("Angle X:"), _("Angle of infinite vanishing point in X direction"),
- "tools.shapes.3dbox", "dir_vp_x", persp->get_vanishing_point (Box3D::X)->get_angle(),
- GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
- 0.0, 360.0, 1.0, 10.0,
- 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
- sp_3dbox_vpx_angle_changed,
- 0.1, 1);
- gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
- g_object_set_data(holder, "box3d_angle_x_action", eact);
- if (!persp->get_vanishing_point (Box3D::X)->is_finite()) {
- gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
+ Persp3D *persp = document->current_persp3d;
+
+ EgeAdjustmentAction* box3d_angle_x = 0;
+ EgeAdjustmentAction* box3d_angle_y = 0;
+ EgeAdjustmentAction* box3d_angle_z = 0;
+
+ /* Angle X */
+ {
+ gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
+ 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), NULL, 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 (!persp3d_VP_is_finite(persp, Proj::X)) {
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
} else {
- gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
+ gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
}
- /* toggle VP in X direction */
+
+ /* VP X state */
{
- InkToggleAction* act = ink_toggle_action_new("3DBoxVPXAction",
- _("Toggle VP in X direction"),
- _("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"),
- "toggle_vp_x",
- Inkscape::ICON_SIZE_DECORATION);
- gtk_action_group_add_action(mainActions, GTK_ACTION(act));
- if (persp) {
- toggled = !persp->get_vanishing_point(Box3D::X)->is_finite();
- }
- gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
- /* we connect the signal after setting the state to avoid switching the state again */
- g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_x_changed), holder);
- }
-
- /* angle of VP in Y direction */
- eact = create_adjustment_action("3DBoxPosAngleYAction",
- _("Angle Y"), _("Angle Y:"), _("Angle of infinite vanishing point in Y direction"),
- "tools.shapes.3dbox", "dir_vp_y", persp->get_vanishing_point (Box3D::Y)->get_angle(),
- GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
- 0.0, 360.0, 1.0, 10.0,
- 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
- sp_3dbox_vpy_angle_changed,
- 0.1, 1);
- gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
- g_object_set_data(holder, "box3d_angle_y_action", eact);
- if (!persp->get_vanishing_point (Box3D::Y)->is_finite()) {
- gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
- } else {
- gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
+ 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)"),
+ "toggle_vp_x",
+ Inkscape::ICON_SIZE_DECORATION );
+ 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_get_int_attribute( "tools.shapes.3dbox", "vp_x_state", 1 ) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_x_state", 1 ) );
}
- /* toggle VP in Y direction */
+ /* Angle Y */
{
- InkToggleAction* act = ink_toggle_action_new("3DBoxVPYAction",
- _("Toggle VP in Y direction"),
- _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
- "toggle_vp_y",
- Inkscape::ICON_SIZE_DECORATION);
- gtk_action_group_add_action(mainActions, GTK_ACTION(act));
- if (persp) {
- toggled = !persp->get_vanishing_point(Box3D::Y)->is_finite();
- }
- gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
- /* we connect the signal after setting the state to avoid switching the state again */
- g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_y_changed), holder);
- }
-
- /* angle of VP in Z direction */
- eact = create_adjustment_action("3DBoxPosAngleZAction",
- _("Angle Z"), _("Angle Z:"), _("Angle of infinite vanishing point in Z direction"),
- "tools.shapes.3dbox", "dir_vp_z", persp->get_vanishing_point (Box3D::Z)->get_angle(),
- GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
- 0.0, 360.0, 1.0, 10.0,
- 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
- sp_3dbox_vpz_angle_changed,
- 0.1, 1);
-
- gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
- g_object_set_data(holder, "box3d_angle_z_action", eact);
- if (!persp->get_vanishing_point (Box3D::Z)->is_finite()) {
- gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
+ gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
+ 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), NULL, holder, FALSE, NULL,
+ -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;
+ }
+
+ if (!persp3d_VP_is_finite(persp, Proj::Y)) {
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
} else {
- gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
+ gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
+ }
+
+ /* 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)"),
+ "toggle_vp_y",
+ Inkscape::ICON_SIZE_DECORATION );
+ 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_get_int_attribute( "tools.shapes.3dbox", "vp_y_state", 1 ) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_y_state", 1 ) );
}
- /* toggle VP in Z direction */
+ /* Angle Z */
{
- InkToggleAction* act = ink_toggle_action_new("3DBoxVPZAction",
- _("Toggle VP in Z direction"),
- _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
- "toggle_vp_z",
- Inkscape::ICON_SIZE_DECORATION);
- gtk_action_group_add_action(mainActions, GTK_ACTION(act));
- if (persp) {
- toggled = !persp->get_vanishing_point(Box3D::Z)->is_finite();
+ gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 };
+ 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), NULL, holder, FALSE, NULL,
+ -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 (!persp3d_VP_is_finite(persp, Proj::Z)) {
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ } else {
+ gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
}
- /* we connect the signal after setting the state to avoid switching the state again */
- gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
- g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_z_changed), holder);
+
+ /* 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)"),
+ "toggle_vp_z",
+ Inkscape::ICON_SIZE_DECORATION );
+ 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_get_int_attribute( "tools.shapes.3dbox", "vp_z_state", 1 ) );
+ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_z_state", 1 ) );
}
sigc::connection *connection = new sigc::connection(
- sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_3dbox_toolbox_selection_changed), (GObject *)holder))
+ sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(box3d_toolbox_selection_changed), (GObject *)holder))
);
g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection);
g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
namespace {
-bool visible = false;
+bool popdown_visible = false;
+bool popdown_hasfocus = false;
void
sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *tbl)
{
SPStyle *query =
sp_style_new (SP_ACTIVE_DOCUMENT);
+
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
int result_family =
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
@@ -3924,15 +4021,27 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
gtk_entry_set_text (GTK_ENTRY (entry), "");
- } else if (query->text->font_family.value) {
+ } else if (query->text->font_specification.value || query->text->font_family.value) {
GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
- gtk_entry_set_text (GTK_ENTRY (entry), query->text->font_family.value);
+
+ // Get the font that corresponds
+ Glib::ustring familyName;
+
+ font_instance * font = font_factory::Default()->FaceFromStyle(query);
+ if (font) {
+ familyName = font_factory::Default()->GetUIFamilyString(font->descr);
+ font->Unref();
+ font = NULL;
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (entry), familyName.c_str());
Gtk::TreePath path;
try {
- path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
+ path = Inkscape::FontLister::get_instance()->get_row_for_font (familyName);
} catch (...) {
+ g_warning("Family name %s does not have an entry in the font lister.", familyName.c_str());
return;
}
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
GtkTreeModel *model = 0;
- GtkWidget *popdown = GTK_WIDGET (g_object_get_data (tbl, "family-popdown-window"));
GtkWidget *entry = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
GtkTreeIter iter;
char *family = 0;
- (void)popdown;
-
gdk_pointer_ungrab (GDK_CURRENT_TIME);
gdk_keyboard_ungrab (GDK_CURRENT_TIME);
SPStyle *query =
sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+ font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
+
SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "font-family", family);
+
+
+ // First try to get the font spec from the stored value
+ Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
+
+ if (fontSpec.empty()) {
+ // Construct a new font specification if it does not yet exist
+ font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
+ fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
+ fontFromStyle->Unref();
+ }
+
+ if (!fontSpec.empty()) {
+ Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
+ if (!newFontSpec.empty() && fontSpec != newFontSpec) {
+ font_instance *font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
+ if (font) {
+ sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
+
+ // Set all the these just in case they were altered when finding the best
+ // match for the new family and old style...
+
+ gchar c[256];
+
+ font->Family(c, 256);
+ sp_repr_css_set_property (css, "font-family", c);
+
+ font->Attribute( "weight", c, 256);
+ sp_repr_css_set_property (css, "font-weight", c);
+
+ font->Attribute("style", c, 256);
+ sp_repr_css_set_property (css, "font-style", c);
+
+ font->Attribute("stretch", c, 256);
+ sp_repr_css_set_property (css, "font-stretch", c);
+
+ font->Attribute("variant", c, 256);
+ sp_repr_css_set_property (css, "font-variant", c);
+
+ font->Unref();
+ }
+ }
+ }
- // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_numbers == QUERY_STYLE_NOTHING)
+ // If querying returned nothing, set the default style of the tool (for new texts)
+ if (result_fontspec == QUERY_STYLE_NOTHING)
{
sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
int prop = GPOINTER_TO_INT(data);
bool active = gtk_toggle_button_get_active (button);
+ SPStyle *query =
+ sp_style_new (SP_ACTIVE_DOCUMENT);
+
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ int result_family =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+
+ int result_style =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ int result_numbers =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+
+ Glib::ustring fontSpec = query->text->font_specification.set ? query->text->font_specification.value : "";
+ Glib::ustring newFontSpec = "";
+
+ if (fontSpec.empty()) {
+ // Construct a new font specification if it does not yet exist
+ font_instance * fontFromStyle = font_factory::Default()->FaceFromStyle(query);
+ fontSpec = font_factory::Default()->ConstructFontSpecification(fontFromStyle);
+ fontFromStyle->Unref();
+ }
+
switch (prop)
{
case 0:
{
- sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
+ if (!fontSpec.empty()) {
+ newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active);
+ }
+ if (fontSpec != newFontSpec) {
+ // Don't even set the bold if the font didn't exist on the system
+ sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
+ }
break;
}
case 1:
{
- sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
+ if (!fontSpec.empty()) {
+ newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active);
+ }
+ if (fontSpec != newFontSpec) {
+ // Don't even set the italic if the font didn't exist on the system
+ sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
+ }
break;
}
}
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (!newFontSpec.empty()) {
+ sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
+ }
// If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_numbers == QUERY_STYLE_NOTHING)
+ if (result_fontspec == QUERY_STYLE_NOTHING)
{
sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
}
gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
}
-gboolean
-sp_text_toolbox_size_keypress (GtkWidget */*w*/, GdkEventKey *event, gpointer /*data*/)
-{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (!desktop) return FALSE;
-
- switch (get_group0_keyval (event)) {
- case GDK_Escape: // defocus
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- return TRUE; // I consumed the event
- break;
- case GDK_Return: // defocus
- case GDK_KP_Enter:
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
- return TRUE; // I consumed the event
- break;
- }
- return FALSE;
-}
-
gboolean
sp_text_toolbox_family_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl)
{
@@ -4338,10 +4503,19 @@ sp_text_toolbox_family_list_keypress (GtkWidget *w, GdkEventKey *event, GObject
case GDK_Return:
case GDK_Escape: // defocus
gtk_widget_hide (w);
- visible = false;
+ popdown_visible = false;
gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
return TRUE; // I consumed the event
break;
+ case GDK_w:
+ case GDK_W:
+ if (event->state & GDK_CONTROL_MASK) {
+ gtk_widget_hide (w);
+ popdown_visible = false;
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ return TRUE; // I consumed the event
+ }
+ break;
}
return FALSE;
}
if (g_object_get_data (tbl, "size-block")) return;
-#if GTK_CHECK_VERSION(2,6,0)
- char *text = gtk_combo_box_get_active_text (cbox);
-#else // GTK_CHECK_VERSION(2,6,0)
- GtkTreeModel *model = gtk_combo_box_get_model (cbox);
- GtkTreeIter iter;
- char *text = NULL;
+ // If this is not from selecting a size in the list (in which case get_active will give the
+ // index of the selected item, otherwise -1) and not from user pressing Enter/Return, do not
+ // process this event. This fixes GTK's stupid insistence on sending an activate change every
+ // time any character gets typed or deleted, which made this control nearly unusable in 0.45.
+ if (gtk_combo_box_get_active (cbox) < 0 && !g_object_get_data (tbl, "enter-pressed"))
+ return;
- if (gtk_combo_box_get_active_iter (cbox, &iter) && model)
- gtk_tree_model_get (model, &iter, 0, &text, -1);
-#endif // GTK_CHECK_VERSION(2,6,0)
+ gchar *endptr;
+ gdouble value = -1;
+ char *text = gtk_combo_box_get_active_text (cbox);
+ if (text) {
+ value = g_strtod (text, &endptr);
+ if (endptr == text) // conversion failed, non-numeric input
+ value = -1;
+ free (text);
+ }
+ if (value <= 0) {
+ return; // could not parse value
+ }
SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "font-size", text);
- free (text);
+ Inkscape::CSSOStringStream osfs;
+ osfs << value;
+ sp_repr_css_set_property (css, "font-size", osfs.str().c_str());
SPStyle *query =
sp_style_new (SP_ACTIVE_DOCUMENT);
_("Text: Change font size"));
sp_repr_css_attr_unref (css);
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+}
- if (gtk_combo_box_get_active (cbox) > 0) // if this was from drop-down (as opposed to type-in), defocus
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+gboolean
+sp_text_toolbox_size_focusout (GtkWidget */*w*/, GdkEventFocus *event, GObject *tbl)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return FALSE;
+
+ if (!g_object_get_data (tbl, "esc-pressed")) {
+ g_object_set_data (tbl, "enter-pressed", gpointer(1));
+ GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
+ sp_text_toolbox_size_changed (cbox, tbl);
+ g_object_set_data (tbl, "enter-pressed", gpointer(0));
+ }
+ return FALSE; // I consumed the event
+}
+
+
+gboolean
+sp_text_toolbox_size_keypress (GtkWidget */*w*/, GdkEventKey *event, GObject *tbl)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop) return FALSE;
+
+ switch (get_group0_keyval (event)) {
+ case GDK_Escape: // defocus
+ g_object_set_data (tbl, "esc-pressed", gpointer(1));
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ g_object_set_data (tbl, "esc-pressed", gpointer(0));
+ return TRUE; // I consumed the event
+ break;
+ case GDK_Return: // defocus
+ case GDK_KP_Enter:
+ g_object_set_data (tbl, "enter-pressed", gpointer(1));
+ GtkComboBox *cbox = GTK_COMBO_BOX(g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
+ sp_text_toolbox_size_changed (cbox, tbl);
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ g_object_set_data (tbl, "enter-pressed", gpointer(0));
+ return TRUE; // I consumed the event
+ break;
+ }
+ return FALSE;
}
void
GtkWidget *widget = GTK_WIDGET (g_object_get_data (tbl, "family-entry"));
int x, y;
- if (!visible)
+ if (!popdown_visible)
{
gdk_window_get_origin (widget->window, &x, &y);
gtk_window_move (GTK_WINDOW (popdown), x, y + widget->allocation.height + 2); //2px of grace space
gtk_widget_show_all (popdown);
+ //sp_transientize (popdown);
gdk_pointer_grab (widget->window, TRUE,
GdkEventMask (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME);
- visible = true;
+ popdown_visible = true;
}
else
{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
gdk_pointer_ungrab (GDK_CURRENT_TIME);
gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
gtk_widget_hide (popdown);
- visible = false;
+ popdown_visible = false;
}
}
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- gtk_widget_hide (popdown);
- visible = false;
- gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ if (popdown_hasfocus) {
+ gtk_widget_hide (popdown);
+ popdown_hasfocus = false;
+ popdown_visible = false;
+ gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+sp_text_toolbox_popdown_focus_in (GtkWidget *popdown,
+ GdkEventFocus */*event*/,
+ GObject */*tbl*/)
+{
+ popdown_hasfocus = true;
return TRUE;
}
+
void
cell_data_func (GtkTreeViewColumn */*column*/,
GtkCellRenderer *cell,
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (Glib::unwrap(store)));
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
-#if GTK_CHECK_VERSION(2,6,0)
gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (treeview), TRUE);
-#endif // GTK_CHECK_VERSION(2,6,0)
//gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (sp_text_toolbox_text_popdown_clicked), tbl);
g_signal_connect (G_OBJECT (window), "focus-out-event", G_CALLBACK (sp_text_toolbox_popdown_focus_out), tbl);
+ g_signal_connect (G_OBJECT (window), "focus-in-event", G_CALLBACK (sp_text_toolbox_popdown_focus_in), tbl);
g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK(sp_text_toolbox_family_list_keypress), tbl);
GtkTreeSelection *tselection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_box_pack_start (GTK_BOX (tbl), cbox, FALSE, FALSE, 0);
g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
g_signal_connect (G_OBJECT (cbox), "changed", G_CALLBACK (sp_text_toolbox_size_changed), tbl);
- gtk_signal_connect(GTK_OBJECT(cbox), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), NULL);
+ gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "key-press-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_keypress), tbl);
+ gtk_signal_connect(GTK_OBJECT(gtk_bin_get_child(GTK_BIN(cbox))), "focus-out-event", GTK_SIGNAL_FUNC(sp_text_toolbox_size_focusout), tbl);
//spacer
aux_toolbox_space (tbl, 4);
Inkscape::ConnectionPool::connect_destroy (G_OBJECT (tbl), pool);
-#if 0
- // horizontal
- {
- GtkWidget *px= sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_LR);
- GtkWidget *b = group = gtk_radio_button_new (NULL);
- gtk_container_add (GTK_CONTAINER (b), px);
- gtk_tooltips_set_tip (tt, b, _("Horizontal text"), NULL);
- gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
- gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
- }
-
- // vertical
- {
- GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_WRITING_MODE_TB);
- GtkWidget *b = gtk_radio_button_new (gtk_radio_button_group (GTK_RADIO_BUTTON (group)));
- gtk_container_add (GTK_CONTAINER (b), px);
- gtk_tooltips_set_tip (tt, b, _("Vertical text"), NULL);
- gtk_button_set_relief (GTK_BUTTON (b), GTK_RELIEF_NONE);
- gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (b), FALSE );
- gtk_box_pack_start (GTK_BOX (tbl), b, FALSE, FALSE, 0);
- }
-
- aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
-
- // letter spacing
- {
- {
- GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LETTER_SPACING);
- GtkWidget *hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add (GTK_CONTAINER (hb), image);
- gtk_widget_show(image);
- gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
- }
-
- {
- GtkWidget *hb = sp_tb_spinbutton((""), _("Spacing between letters"),
- "tools.text", "letter_spacing", 0.0,
- us, tbl, FALSE, NULL,
- -1000.0, 1000.0, 0.1, 0.1,
- sp_text_letter_changed, 0.1, 1);
- gtk_widget_set_size_request (hb, 45, 6);
- gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
- }
- }
-
- // line spacing
- {
- {
- GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_LINE_SPACING);
- GtkWidget *hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add (GTK_CONTAINER (hb), image);
- gtk_widget_show(image);
- gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
- }
-
- {
- GtkWidget *hb = sp_tb_spinbutton((""), _("Spacing between lines"),
- "tools.text", "line_spacing", 0,
- us, tbl, FALSE, NULL,
- -1000.0, 1000.0, 0.1, 0.1,
- sp_text_line_changed, 0.1, 1);
- gtk_widget_set_size_request (hb, 45, 0);
- gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 3);
- }
- }
-
- {
- // horizontal kerning/vertical kerning units menu: create
- 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_set_unit(SP_UNIT_SELECTOR(us), desktop->namedview->doc_units);
-
- aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
-
- // horizontal kerning
- {
- {
- GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_HORZ_KERN);
- GtkWidget *hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add (GTK_CONTAINER (hb), image);
- gtk_widget_show(image);
- gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
- }
-
- {
- GtkWidget *hb = sp_tb_spinbutton((""), _("Horizontal kerning"),
- "tools.text", "horizontal_kerning", 0,
- us, tbl, FALSE, NULL,
- -100.00, 100.00, 0.01, 0.1,
- sp_text_horiz_kern_changed);
- gtk_widget_set_size_request (hb, 45, 0);
- gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
- }
- }
-
- // vertical kerning
- {
- {
- GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_VERT_KERN);
- GtkWidget *hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add (GTK_CONTAINER (hb), image);
- gtk_widget_show(image);
- gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
- }
-
- {
- GtkWidget *hb = sp_tb_spinbutton((""), _("Vertical kerning"),
- "tools.text", "vertical_kerning", 0,
- us, tbl, FALSE, NULL,
- -100.00, 100.00, 0.01, 0.1,
- sp_text_vert_kern_changed);
- gtk_widget_set_size_request (hb, 45, 0);
- gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 5);
- }
- }
-
- // add the units menu
- gtk_widget_show(us);
- gtk_box_pack_start(GTK_BOX(tbl), us, FALSE, FALSE, 1);
- gtk_object_set_data(GTK_OBJECT(tbl), "units", us);
- }
-
- // letter rotation
- aux_toolbox_space(tbl, AUX_BETWEEN_BUTTON_GROUPS);
- {
- {
- GtkWidget *image = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_ROTATION);
- GtkWidget *hb = gtk_hbox_new(FALSE, 1);
- gtk_container_add (GTK_CONTAINER (hb), image);
- gtk_widget_show(image);
- gtk_box_pack_start (GTK_BOX (tbl), hb, FALSE, FALSE, 0);
- }
- {
- GtkWidget *hb = sp_tb_spinbutton((""), _("Letter rotation"),
- "tools.text", "letter_rotation", 0,
- us, tbl, FALSE, NULL,
- -180.0, 180.0, 0.1, 0.1,
- sp_text_letter_rotation_changed, 0.1, 1);
- gtk_widget_set_size_request (hb, 45, 0);
- gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, 6);
- }
- // rotation degree label
- {
- GtkWidget *label = gtk_widget_new (GTK_TYPE_LABEL, "label", "\302\260", "xalign", 0.0, NULL);
- gtk_box_pack_start(GTK_BOX(tbl), label, FALSE, FALSE, 0);
- }
- }
-
- // Remove Manual Kerns
- {
- GtkWidget *px = sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_STOCK_TEXT_REMOVE_KERNS);
- GtkWidget *button = gtk_button_new ();
- gtk_container_add (GTK_CONTAINER (button), px);
- gtk_widget_show(button);
- gtk_tooltips_set_tip (tt, button, _("Remove manual kerns"), NULL);
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
- gtk_widget_set_sensitive(button, TRUE);
- gtk_box_pack_start (GTK_BOX (tbl), button, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
- }
-#endif
-
gtk_widget_show_all (tbl);
return tbl;
@@ -5246,7 +5325,9 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
// Create the units menu.
UnitTracker* tracker = new UnitTracker( SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE );
- tracker->setActiveUnit(sp_unit_get_by_abbreviation(prefs_get_string_attribute("tools.paintbucket", "offsetunits")));
+ const gchar *stored_unit = prefs_get_string_attribute("tools.paintbucket", "offsetunits");
+ if (stored_unit)
+ tracker->setActiveUnit(sp_unit_get_by_abbreviation(stored_unit));
g_object_set_data( holder, "tracker", tracker );
{
GtkAction* act = tracker->createAction( "PaintbucketUnitsAction", _("Units"), ("") );
@@ -5316,3 +5397,6 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
+
+