X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fwidgets%2Fdesktop-widget.cpp;h=4620b15328e0137603f11dcf50078cf0426513a5;hb=c580a96092327174256078a5ca30582608e82be7;hp=d7b8ac1702390150476d0249a7ef0e009cc54218;hpb=963f23115db07f460bdd862b957f8bd9dba88b9b;p=inkscape.git diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index d7b8ac170..4620b1532 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1,15 +1,15 @@ -#define __SP_DESKTOP_WIDGET_C__ - /** \file * Desktop widget implementation - * - * Authors: + */ +/* Authors: * Lauris Kaplinski * MenTaLguY * bulia byak * Ralf Stephan * John Bintz * Johan Engelen + * Jon A. Cruz + * Abhishek Sharma * * Copyright (C) 2007 Johan Engelen * Copyright (C) 2006 John Bintz @@ -27,44 +27,55 @@ #include #include -#include "macros.h" -#include "inkscape-private.h" -#include "desktop-handles.h" +#include "box3d-context.h" +#include "color-profile-fns.h" +#include "conn-avoid-ref.h" #include "desktop-events.h" -#include "document.h" +#include "desktop-handles.h" #include "desktop-widget.h" -#include "sp-namedview.h" -#include "interface.h" -#include "toolbox.h" -#include "prefs-utils.h" -#include "preferences.h" -#include "file.h" #include "display/canvas-arena.h" #include "display/nr-arena.h" +#include "document.h" +#include "ege-color-prof-tracker.h" +#include "ege-select-one-action.h" #include +#include "file.h" #include "helper/units.h" -#include "widgets/button.h" -#include "widgets/ruler.h" -#include "widgets/widget-sizes.h" -#include "widgets/spw-utilities.h" -#include "widgets/spinbutton-events.h" -#include "widgets/layer-selector.h" +#include "helper/unit-tracker.h" +#include "inkscape-private.h" +#include "interface.h" +#include "macros.h" +#include "preferences.h" +#include "sp-image.h" +#include "sp-item.h" +#include "sp-namedview.h" #include "ui/dialog/dialog-manager.h" +#include "ui/dialog/swatches.h" +#include "ui/icon-names.h" #include "ui/widget/dock.h" +#include "ui/widget/layer-selector.h" #include "ui/widget/selected-style.h" -#include "sp-item.h" -#include "dialogs/swatches.h" -#include "conn-avoid-ref.h" -#include "ege-select-one-action.h" -#include "ege-color-prof-tracker.h" -#include "dom/util/digest.h" -#include "xml/node-observer.h" +#include "ui/uxmanager.h" +#include "util/ege-appear-time-tracker.h" + +// We're in the "widgets" directory, so no need to explicitly prefix these: +#include "button.h" +#include "ruler.h" +#include "spinbutton-events.h" +#include "spw-utilities.h" +#include "toolbox.h" +#include "widget-sizes.h" -#if defined (SOLARIS_2_8) +#if defined (SOLARIS) && (SOLARIS == 8) #include "round.h" using Inkscape::round; #endif +using Inkscape::UnitTracker; +using Inkscape::UI::UXManager; +using Inkscape::UI::ToolboxFactory; +using ege::AppearTimeTracker; + #ifdef WITH_INKBOARD #endif @@ -83,7 +94,6 @@ enum { /* SPDesktopWidget */ static void sp_desktop_widget_class_init (SPDesktopWidgetClass *klass); -static void sp_desktop_widget_init (SPDesktopWidget *widget); static void sp_desktop_widget_destroy (GtkObject *object); static void sp_desktop_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation); @@ -93,8 +103,8 @@ static gint sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDeskt static void sp_dtw_color_profile_event(EgeColorProfTracker *widget, SPDesktopWidget *dtw); static void cms_adjust_toggled( GtkWidget *button, gpointer data ); +static void cms_adjust_set_sensitive( SPDesktopWidget *dtw, bool enabled ); static void sp_desktop_widget_adjustment_value_changed (GtkAdjustment *adj, SPDesktopWidget *dtw); -static void sp_desktop_widget_namedview_modified (SPObject *obj, guint flags, SPDesktopWidget *dtw); static gdouble sp_dtw_zoom_value_to_display (gdouble value); static gdouble sp_dtw_zoom_display_to_value (gdouble value); @@ -109,93 +119,132 @@ static void sp_dtw_zoom_200 (GtkMenuItem *item, gpointer data); static void sp_dtw_zoom_page (GtkMenuItem *item, gpointer data); static void sp_dtw_zoom_drawing (GtkMenuItem *item, gpointer data); static void sp_dtw_zoom_selection (GtkMenuItem *item, gpointer data); +static void sp_dtw_sticky_zoom_toggled (GtkMenuItem *item, gpointer data); SPViewWidgetClass *dtw_parent_class; -using Inkscape::XML::Node; +static GTimer *baseTimer = 0; +static bool timeReported = false; + +static void timeGoing(gchar const* id) +{ + if ( !baseTimer ) { + g_message("Starting time at point [%s]", id); + baseTimer = g_timer_new(); + } +} + +static void checkTime(gchar const* msg) +{ + if ( baseTimer && !timeReported ) { + timeReported = true; + g_timer_stop(baseTimer); + gulong msCount = 0; + gdouble secs = g_timer_elapsed( baseTimer, &msCount ); + g_message("Time ended at %2.3f with [%s]", secs, msg); + } +} + + -class PrefWatcher : public Inkscape::XML::NodeObserver { +class CMSPrefWatcher { public: - PrefWatcher() : - NodeObserver(), - dtws() + CMSPrefWatcher() : + _dpw(*this), + _spw(*this), + _tracker(ege_color_prof_tracker_new(0)) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + g_signal_connect( G_OBJECT(_tracker), "modified", G_CALLBACK(hook), this ); + prefs->addObserver(_dpw); + prefs->addObserver(_spw); } + virtual ~CMSPrefWatcher() {} - virtual ~PrefWatcher(); + //virtual void notify(PrefValue &); + void add( SPDesktopWidget* dtw ) { + _widget_list.push_back(dtw); + } + void remove( SPDesktopWidget* dtw ) { + _widget_list.remove(dtw); + } +private: + static void hook(EgeColorProfTracker *tracker, gint a, gint b, CMSPrefWatcher *watcher); + + class DisplayProfileWatcher : public Inkscape::Preferences::Observer { + public: + DisplayProfileWatcher(CMSPrefWatcher &pw) : Observer("/options/displayprofile"), _pw(pw) {} + virtual void notify(Inkscape::Preferences::Entry const &/*val*/) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _pw._setCmsSensitive(!prefs->getString("/options/displayprofile/uri").empty()); + _pw._refreshAll(); + } + private: + CMSPrefWatcher &_pw; + }; - virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) {} - virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) {} - virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, - Node */*old_prev*/, Node */*new_prev*/ ) {} - virtual void notifyContentChanged( Node &/*node*/, - Inkscape::Util::ptr_shared /*old_content*/, - Inkscape::Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &node, GQuark name, - Inkscape::Util::ptr_shared old_value, - Inkscape::Util::ptr_shared new_value ); - void add( SPDesktopWidget* dtw ); - void remove( SPDesktopWidget* dtw ); + DisplayProfileWatcher _dpw; -private: - std::list dtws; + class SoftProofWatcher : public Inkscape::Preferences::Observer { + public: + SoftProofWatcher(CMSPrefWatcher &pw) : Observer("/options/softproof"), _pw(pw) {} + virtual void notify(Inkscape::Preferences::Entry const &) { + _pw._refreshAll(); + } + private: + CMSPrefWatcher &_pw; + }; + + SoftProofWatcher _spw; + + void _refreshAll(); + void _setCmsSensitive(bool value); + + std::list _widget_list; + EgeColorProfTracker *_tracker; + + friend class DisplayProfileWatcher; + friend class SoftproofWatcher; }; -PrefWatcher::~PrefWatcher() +void CMSPrefWatcher::hook(EgeColorProfTracker */*tracker*/, gint screen, gint monitor, CMSPrefWatcher */*watcher*/) { -} +#if ENABLE_LCMS + unsigned char* buf = 0; + guint len = 0; -void PrefWatcher::add( SPDesktopWidget* dtw ) -{ - dtws.push_back(dtw); + ege_color_prof_tracker_get_profile_for( screen, monitor, reinterpret_cast(&buf), &len ); + Glib::ustring id = Inkscape::colorprofile_set_display_per( buf, len, screen, monitor ); +#endif // ENABLE_LCMS } -void PrefWatcher::remove( SPDesktopWidget* dtw ) +/// @todo Use conditional compilation in saner places. The whole PrefWatcher +/// object is unnecessary if ENABLE_LCMS is not defined. +void CMSPrefWatcher::_refreshAll() { - dtws.remove(dtw); +#if ENABLE_LCMS + for ( std::list::iterator it = _widget_list.begin(); it != _widget_list.end(); ++it ) { + (*it)->requestCanvasUpdate(); + } +#endif // ENABLE_LCMS } -void PrefWatcher::notifyAttributeChanged( Node &node, GQuark name, - Inkscape::Util::ptr_shared /*old_value*/, - Inkscape::Util::ptr_shared /*new_value*/ ) +void CMSPrefWatcher::_setCmsSensitive(bool enabled) { #if ENABLE_LCMS - (void)name; - if ( strcmp("group", node.name()) == 0 ) { - gchar const* id = node.attribute("id"); - bool refresh = false; - if ( !id ) { - // bad - } else if (strcmp("displayprofile", id) == 0) { - Glib::ustring current = prefs_get_string_attribute( "options.displayprofile", "uri" ); - bool enabled = current.length() > 0; - - for ( std::list::iterator it = dtws.begin(); it != dtws.end(); ++it ) { - SPDesktopWidget* dtw = *it; - if ( GTK_WIDGET_SENSITIVE( dtw->cms_adjust ) != enabled ) { - gtk_widget_set_sensitive( dtw->cms_adjust, enabled ); - } - } - refresh = true; - } else if (strcmp("softproof", id) == 0) { - refresh = true; - } - - if ( refresh ) { - for ( std::list::iterator it = dtws.begin(); it != dtws.end(); ++it ) { - (*it)->requestCanvasUpdate(); - } + for ( std::list::iterator it = _widget_list.begin(); it != _widget_list.end(); ++it ) { + SPDesktopWidget *dtw = *it; + if ( GTK_WIDGET_SENSITIVE( dtw->cms_adjust ) != enabled ) { + cms_adjust_set_sensitive( dtw, enabled ); } + } #else - (void)node; - (void)name; - (void)new_value; + (void) enabled; #endif // ENABLE_LCMS - } } -static PrefWatcher* watcher = 0; +static CMSPrefWatcher* watcher = NULL; void SPDesktopWidget::setMessage (Inkscape::MessageType type, const gchar *message) @@ -209,35 +258,42 @@ SPDesktopWidget::setMessage (Inkscape::MessageType type, const gchar *message) gdk_window_process_updates(GTK_WIDGET(sb)->window, TRUE); } - // FIXME: TODO: remove before displaying as tooltip - gtk_tooltips_set_tip (this->tt, this->select_status_eventbox, message ? message : "", NULL); + gtk_tooltips_set_tip (this->tt, this->select_status_eventbox, gtk_label_get_text (sb) , NULL); } -NR::Point +Geom::Point SPDesktopWidget::window_get_pointer() { gint x,y; gdk_window_get_pointer (GTK_WIDGET (canvas)->window, &x, &y, NULL); - return NR::Point(x,y); + return Geom::Point(x,y); } +static GTimer *overallTimer = 0; + /** * Registers SPDesktopWidget class and returns its type number. */ -GtkType -sp_desktop_widget_get_type (void) +GType SPDesktopWidget::getType(void) { static GtkType type = 0; if (!type) { - static const GtkTypeInfo info = { - "SPDesktopWidget", - sizeof (SPDesktopWidget), - sizeof (SPDesktopWidgetClass), - (GtkClassInitFunc) sp_desktop_widget_class_init, - (GtkObjectInitFunc) sp_desktop_widget_init, - NULL, NULL, NULL + timeGoing("SPDesktopWidget::getType"); + GTypeInfo info = { + sizeof(SPDesktopWidgetClass), + 0, // base_init + 0, // base_finalize + (GClassInitFunc)sp_desktop_widget_class_init, + 0, // class_finalize + 0, // class_data + sizeof(SPDesktopWidget), + 0, // n_preallocs + (GInstanceInitFunc)SPDesktopWidget::init, + 0 // value_table }; - type = gtk_type_unique (SP_TYPE_VIEW_WIDGET, &info); + type = g_type_register_static(SP_TYPE_VIEW_WIDGET, "SPDesktopWidget", &info, static_cast(0)); + // Begin a timer to watch for the first desktop to appear on-screen + overallTimer = g_timer_new(); } return type; } @@ -248,6 +304,7 @@ sp_desktop_widget_get_type (void) static void sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) { + timeGoing("sp_desktop_widget_class_init"); dtw_parent_class = (SPViewWidgetClass*)gtk_type_class (SP_TYPE_VIEW_WIDGET); GtkObjectClass *object_class = (GtkObjectClass *) klass; @@ -262,27 +319,25 @@ sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) /** * Callback for SPDesktopWidget object initialization. */ -static void -sp_desktop_widget_init (SPDesktopWidget *dtw) +void SPDesktopWidget::init( SPDesktopWidget *dtw ) { + timeGoing("SPDesktopWidget::init"); GtkWidget *widget; GtkWidget *tbl; GtkWidget *canvas_tbl; - GtkWidget *hbox; GtkWidget *eventbox; GtkStyle *style; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + new (&dtw->modified_connection) sigc::connection(); widget = GTK_WIDGET (dtw); dtw->window = 0; - dtw->desktop = NULL; - dtw->_interaction_disabled_counter = 0; - dtw->tt = gtk_tooltips_new (); /* Main table */ @@ -296,27 +351,31 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) { using Inkscape::UI::Dialogs::SwatchesPanel; - SwatchesPanel* swatches = new SwatchesPanel("embedded.swatches"); - swatches->setOrientation( Gtk::ANCHOR_SOUTH ); - dtw->panels = GTK_WIDGET(swatches->gobj()); - gtk_box_pack_end( GTK_BOX( dtw->vbox ), dtw->panels, FALSE, TRUE, 0 ); + dtw->panels = new SwatchesPanel("/embedded/swatches"); + dtw->panels->setOrientation( Gtk::ANCHOR_SOUTH ); + gtk_box_pack_end( GTK_BOX( dtw->vbox ), GTK_WIDGET(dtw->panels->gobj()), FALSE, TRUE, 0 ); } - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_end (GTK_BOX (dtw->vbox), hbox, TRUE, TRUE, 0); - gtk_widget_show (hbox); - - dtw->aux_toolbox = sp_aux_toolbox_new (); + dtw->hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_end( GTK_BOX (dtw->vbox), dtw->hbox, TRUE, TRUE, 0 ); + gtk_widget_show(dtw->hbox); + + dtw->aux_toolbox = ToolboxFactory::createAuxToolbox(); gtk_box_pack_end (GTK_BOX (dtw->vbox), dtw->aux_toolbox, FALSE, TRUE, 0); - dtw->commands_toolbox = sp_commands_toolbox_new (); + dtw->snap_toolbox = ToolboxFactory::createSnapToolbox(); + ToolboxFactory::setOrientation( dtw->snap_toolbox, GTK_ORIENTATION_VERTICAL ); + gtk_box_pack_end( GTK_BOX(dtw->hbox), dtw->snap_toolbox, FALSE, TRUE, 0 ); + + dtw->commands_toolbox = ToolboxFactory::createCommandsToolbox(); gtk_box_pack_end (GTK_BOX (dtw->vbox), dtw->commands_toolbox, FALSE, TRUE, 0); - dtw->tool_toolbox = sp_tool_toolbox_new (); - gtk_box_pack_start (GTK_BOX (hbox), dtw->tool_toolbox, FALSE, TRUE, 0); + dtw->tool_toolbox = ToolboxFactory::createToolToolbox(); + ToolboxFactory::setOrientation( dtw->tool_toolbox, GTK_ORIENTATION_VERTICAL ); + gtk_box_pack_start( GTK_BOX(dtw->hbox), dtw->tool_toolbox, FALSE, TRUE, 0 ); tbl = gtk_table_new (2, 3, FALSE); - gtk_box_pack_start (GTK_BOX (hbox), tbl, TRUE, TRUE, 1); + gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl, TRUE, TRUE, 1 ); canvas_tbl = gtk_table_new (3, 3, FALSE); @@ -354,29 +413,39 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) dtw->sticky_zoom = sp_button_new_from_data ( Inkscape::ICON_SIZE_DECORATION, SP_BUTTON_TYPE_TOGGLE, NULL, - "sticky_zoom", + INKSCAPE_ICON_ZOOM_ORIGINAL, _("Zoom drawing if window size changes"), dtw->tt); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtw->sticky_zoom), prefs_get_int_attribute ("options.stickyzoom", "value", 0)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtw->sticky_zoom), prefs->getBool("/options/stickyzoom/value")); gtk_box_pack_start (GTK_BOX (dtw->vscrollbar_box), dtw->sticky_zoom, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (dtw->sticky_zoom), "toggled", G_CALLBACK (sp_dtw_sticky_zoom_toggled), dtw); dtw->vadj = (GtkAdjustment *) gtk_adjustment_new (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0); dtw->vscrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (dtw->vadj)); gtk_box_pack_start (GTK_BOX (dtw->vscrollbar_box), dtw->vscrollbar, TRUE, TRUE, 0); gtk_table_attach (GTK_TABLE (canvas_tbl), dtw->vscrollbar_box, 2, 3, 0, 2, (GtkAttachOptions)(GTK_SHRINK), (GtkAttachOptions)(GTK_FILL), 0, 0); + + gchar const* tip = ""; + Inkscape::Verb* verb = Inkscape::Verb::get( SP_VERB_VIEW_CMS_TOGGLE ); + if ( verb ) { + SPAction *act = verb->get_action( dtw->viewwidget.view ); + if ( act && act->tip ) { + tip = act->tip; + } + } dtw->cms_adjust = sp_button_new_from_data( Inkscape::ICON_SIZE_DECORATION, SP_BUTTON_TYPE_TOGGLE, NULL, - "swatches", - _("Adjust the display"), + INKSCAPE_ICON_COLOR_MANAGEMENT, + tip, dtw->tt ); #if ENABLE_LCMS { - Glib::ustring current = prefs_get_string_attribute( "options.displayprofile", "uri" ); + Glib::ustring current = prefs->getString("/options/displayprofile/uri"); bool enabled = current.length() > 0; - gtk_widget_set_sensitive( dtw->cms_adjust, enabled ); + cms_adjust_set_sensitive( dtw, enabled ); if ( enabled ) { - long long int active = prefs_get_int_attribute_limited( "options.displayprofile", "enable", 0, 0, 1 ); + bool active = prefs->getBool("/options/displayprofile/enable"); if ( active ) { sp_button_toggle_set_down( SP_BUTTON(dtw->cms_adjust), TRUE ); } @@ -384,38 +453,33 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) } g_signal_connect_after( G_OBJECT(dtw->cms_adjust), "clicked", G_CALLBACK(cms_adjust_toggled), dtw ); #else - gtk_widget_set_sensitive(dtw->cms_adjust, FALSE); + cms_adjust_set_sensitive(dtw, FALSE); #endif // ENABLE_LCMS gtk_table_attach( GTK_TABLE(canvas_tbl), dtw->cms_adjust, 2, 3, 2, 3, (GtkAttachOptions)(GTK_SHRINK), (GtkAttachOptions)(GTK_SHRINK), 0, 0); { - Inkscape::XML::Node* prefs = Inkscape::Preferences::get(); - if ( prefs ) { - if (!watcher) { - watcher = new PrefWatcher(); - prefs->addSubtreeObserver( *watcher ); - } - watcher->add(dtw); - } else { - g_warning("NULL preferences instance encountered"); + if (!watcher) { + watcher = new CMSPrefWatcher(); } + watcher->add(dtw); } /* Canvas */ dtw->canvas = SP_CANVAS (sp_canvas_new_aa ()); #if ENABLE_LCMS - dtw->canvas->enable_cms_display_adj = prefs_get_int_attribute_limited( "options.displayprofile", "enable", 0, 0, 1 ) != 0; + dtw->canvas->enable_cms_display_adj = prefs->getBool("/options/displayprofile/enable"); #endif // ENABLE_LCMS GTK_WIDGET_SET_FLAGS (GTK_WIDGET (dtw->canvas), GTK_CAN_FOCUS); style = gtk_style_copy (GTK_WIDGET (dtw->canvas)->style); style->bg[GTK_STATE_NORMAL] = style->white; gtk_widget_set_style (GTK_WIDGET (dtw->canvas), style); - gtk_widget_set_extension_events(GTK_WIDGET (dtw->canvas) , GDK_EXTENSION_EVENTS_ALL); + if ( prefs->getBool("/options/useextinput/value", true) ) + gtk_widget_set_extension_events(GTK_WIDGET (dtw->canvas) , GDK_EXTENSION_EVENTS_ALL); //set extension events for tablets, unless disabled in preferences g_signal_connect (G_OBJECT (dtw->canvas), "event", G_CALLBACK (sp_desktop_widget_event), dtw); gtk_table_attach (GTK_TABLE (canvas_tbl), GTK_WIDGET(dtw->canvas), 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), 0, 0); /* Dock */ bool create_dock = - prefs_get_int_attribute_limited ("options.dialogtype", "value", Inkscape::UI::Dialog::FLOATING, 0, 1) == + prefs->getIntLimited("/options/dialogtype/value", Inkscape::UI::Dialog::FLOATING, 0, 1) == Inkscape::UI::Dialog::DOCK; if (create_dock) { @@ -475,10 +539,10 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) eventbox = gtk_event_box_new (); gtk_container_add (GTK_CONTAINER (eventbox), dtw->coord_status); gtk_tooltips_set_tip (dtw->tt, eventbox, _("Cursor coordinates"), NULL); - GtkWidget *label_x = gtk_label_new("X:"); + GtkWidget *label_x = gtk_label_new(_("X:")); gtk_misc_set_alignment (GTK_MISC(label_x), 0.0, 0.5); gtk_table_attach(GTK_TABLE(dtw->coord_status), label_x, 1,2, 0,1, GTK_FILL, GTK_FILL, 0, 0); - GtkWidget *label_y = gtk_label_new("Y:"); + GtkWidget *label_y = gtk_label_new(_("Y:")); gtk_misc_set_alignment (GTK_MISC(label_y), 0.0, 0.5); gtk_table_attach(GTK_TABLE(dtw->coord_status), label_y, 1,2, 1,2, GTK_FILL, GTK_FILL, 0, 0); dtw->coord_status_x = gtk_label_new(NULL); @@ -489,7 +553,7 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) gtk_misc_set_alignment (GTK_MISC(dtw->coord_status_y), 1.0, 0.5); gtk_table_attach(GTK_TABLE(dtw->coord_status), dtw->coord_status_x, 2,3, 0,1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(dtw->coord_status), dtw->coord_status_y, 2,3, 1,2, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach(GTK_TABLE(dtw->coord_status), gtk_label_new("Z:"), 3,4, 0,2, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach(GTK_TABLE(dtw->coord_status), gtk_label_new(_("Z:")), 3,4, 0,2, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(dtw->coord_status), dtw->zoom_status, 4,5, 0,2, GTK_FILL, GTK_FILL, 0, 0); sp_set_font_size_smaller (dtw->coord_status); gtk_box_pack_end (GTK_BOX (statusbar_tail), eventbox, FALSE, FALSE, 1); @@ -501,6 +565,19 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1); dtw->_tracker = ege_color_prof_tracker_new(GTK_WIDGET(dtw->layer_selector->gobj())); +#if ENABLE_LCMS + bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display"); + if ( fromDisplay ) { + Glib::ustring id = Inkscape::colorprofile_get_display_id( 0, 0 ); + + bool enabled = false; + if ( dtw->canvas->cms_key ) { + *(dtw->canvas->cms_key) = id; + enabled = !dtw->canvas->cms_key->empty(); + } + cms_adjust_set_sensitive( dtw, enabled ); + } +#endif // ENABLE_LCMS g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(sp_dtw_color_profile_event), dtw ); dtw->select_status_eventbox = gtk_event_box_new (); @@ -518,6 +595,20 @@ sp_desktop_widget_init (SPDesktopWidget *dtw) gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status_eventbox, TRUE, TRUE, 0); gtk_widget_show_all (dtw->vbox); + + gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas)); + + // If this is the first desktop created, report the time it takes to show up + if ( overallTimer ) { + if ( prefs->getBool("/dialogs/debug/trackAppear", false) ) { + // Time tracker takes ownership of the timer. + AppearTimeTracker *tracker = new AppearTimeTracker(overallTimer, GTK_WIDGET(dtw), "first SPDesktopWidget"); + tracker->setAutodelete(true); + } else { + g_timer_destroy(overallTimer); + } + overallTimer = 0; + } } /** @@ -528,6 +619,8 @@ sp_desktop_widget_destroy (GtkObject *object) { SPDesktopWidget *dtw = SP_DESKTOP_WIDGET (object); + UXManager::getInstance()->delTrack(dtw); + if (dtw->desktop) { if ( watcher ) { watcher->remove(dtw); @@ -572,14 +665,22 @@ SPDesktopWidget::updateTitle(gchar const* uri) : g_basename(uri) ); GString *name = g_string_new (""); if (this->desktop->number > 1) { - if (this->desktop->getMode() == RENDERMODE_OUTLINE) { + if (this->desktop->getMode() == Inkscape::RENDERMODE_OUTLINE) { g_string_printf (name, _("%s: %d (outline) - Inkscape"), fname, this->desktop->number); + } else if (this->desktop->getMode() == Inkscape::RENDERMODE_NO_FILTERS) { + g_string_printf (name, _("%s: %d (no filters) - Inkscape"), fname, this->desktop->number); + } else if (this->desktop->getMode() == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW) { + g_string_printf (name, _("%s: %d (print colors preview) - Inkscape"), fname, this->desktop->number); } else { g_string_printf (name, _("%s: %d - Inkscape"), fname, this->desktop->number); } } else { - if (this->desktop->getMode() == RENDERMODE_OUTLINE) { + if (this->desktop->getMode() == Inkscape::RENDERMODE_OUTLINE) { g_string_printf (name, _("%s (outline) - Inkscape"), fname); + } else if (this->desktop->getMode() == Inkscape::RENDERMODE_NO_FILTERS) { + g_string_printf (name, _("%s (no filters) - Inkscape"), fname); + } else if (this->desktop->getMode() == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW) { + g_string_printf (name, _("%s (print colors preview) - Inkscape"), fname); } else { g_string_printf (name, _("%s - Inkscape"), fname); } @@ -613,7 +714,7 @@ sp_desktop_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation) } if (GTK_WIDGET_REALIZED (widget)) { - NR::Rect const area = dtw->desktop->get_display_area(); + Geom::Rect const area = dtw->desktop->get_display_area(); double zoom = dtw->desktop->current_zoom(); if (GTK_WIDGET_CLASS(dtw_parent_class)->size_allocate) { @@ -621,16 +722,14 @@ sp_desktop_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation) } if (SP_BUTTON_IS_DOWN(dtw->sticky_zoom)) { - /* Calculate zoom per pixel */ - double const zpsp = zoom / hypot (area.dimensions()[NR::X], area.dimensions()[NR::Y]); /* Find new visible area */ - NR::Rect newarea = dtw->desktop->get_display_area(); + Geom::Rect newarea = dtw->desktop->get_display_area(); /* Calculate adjusted zoom */ - zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]); - dtw->desktop->zoom_absolute(newarea.midpoint()[NR::X], newarea.midpoint()[NR::Y], zoom); - } else { - dtw->desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom); + double oldshortside = MIN( area.width(), area.height()); + double newshortside = MIN(newarea.width(), newarea.height()); + zoom *= newshortside / oldshortside; } + dtw->desktop->zoom_absolute(area.midpoint()[Geom::X], area.midpoint()[Geom::Y], zoom); } else { if (GTK_WIDGET_CLASS (dtw_parent_class)->size_allocate) { @@ -655,21 +754,29 @@ sp_desktop_widget_realize (GtkWidget *widget) NRRect d; d.x0 = 0.0; d.y0 = 0.0; - d.x1 = sp_document_width (dtw->desktop->doc()); - d.y1 = sp_document_height (dtw->desktop->doc()); + d.x1 = (dtw->desktop->doc())->getWidth (); + d.y1 = (dtw->desktop->doc())->getHeight (); if ((fabs (d.x1 - d.x0) < 1.0) || (fabs (d.y1 - d.y0) < 1.0)) return; dtw->desktop->set_display_area (d.x0, d.y0, d.x1, d.y1, 10); - /* Listen on namedview modification */ + dtw->updateNamedview(); +} + +/* This is just to provide access to common functionality from sp_desktop_widget_realize() above + as well as from SPDesktop::change_document() */ +void SPDesktopWidget::updateNamedview() +{ + // Listen on namedview modification // originally (prior to the sigc++ conversion) the signal was simply // connected twice rather than disconnecting the first connection - dtw->modified_connection.disconnect(); - dtw->modified_connection = dtw->desktop->namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_desktop_widget_namedview_modified), dtw)); - sp_desktop_widget_namedview_modified (dtw->desktop->namedview, SP_OBJECT_MODIFIED_FLAG, dtw); + modified_connection.disconnect(); + + modified_connection = desktop->namedview->connectModified(sigc::mem_fun(*this, &SPDesktopWidget::namedviewModified)); + namedviewModified(desktop->namedview, SP_OBJECT_MODIFIED_FLAG); - dtw->updateTitle(SP_DOCUMENT_NAME (dtw->desktop->doc())); + updateTitle( desktop->doc()->getName() ); } /** @@ -707,30 +814,54 @@ sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dt return FALSE; } -void sp_dtw_color_profile_event(EgeColorProfTracker *tracker, SPDesktopWidget */*dtw*/) +void sp_dtw_color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidget *dtw) { +#if ENABLE_LCMS // Handle profile changes - Md5Digest digest; - unsigned char* buf = 0; - guint len = 0; - ege_color_prof_tracker_get_profile( tracker, reinterpret_cast(&buf), &len ); - if ( buf && len ) { - digest.append(buf, len); + GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(dtw)); + gint screenNum = gdk_screen_get_number(screen); + gint monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_toplevel(GTK_WIDGET(dtw))->window); + Glib::ustring id = Inkscape::colorprofile_get_display_id( screenNum, monitor ); + bool enabled = false; + if ( dtw->canvas->cms_key ) { + *(dtw->canvas->cms_key) = id; + dtw->requestCanvasUpdate(); + enabled = !dtw->canvas->cms_key->empty(); } - std::string hash = digest.finishHex(); - //g_message("ICC profile %d bytes at %p is [%s]", len, buf, hash.c_str() ); + cms_adjust_set_sensitive( dtw, enabled ); +#endif // ENABLE_LCMS } void cms_adjust_toggled( GtkWidget */*button*/, gpointer data ) { +#if ENABLE_LCMS SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(data); bool down = SP_BUTTON_IS_DOWN(dtw->cms_adjust); if ( down != dtw->canvas->enable_cms_display_adj ) { dtw->canvas->enable_cms_display_adj = down; dtw->requestCanvasUpdate(); - prefs_set_int_attribute( "options.displayprofile", "enable", down ? 1 : 0 ); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/displayprofile/enable", down); + if (down) { + dtw->setMessage (Inkscape::NORMAL_MESSAGE, _("Color-managed display is enabled in this window")); + } else { + dtw->setMessage (Inkscape::NORMAL_MESSAGE, _("Color-managed display is disabled in this window")); + } } +#endif // ENABLE_LCMS +} + +void cms_adjust_set_sensitive( SPDesktopWidget *dtw, bool enabled ) +{ + Inkscape::Verb* verb = Inkscape::Verb::get( SP_VERB_VIEW_CMS_TOGGLE ); + if ( verb ) { + SPAction *act = verb->get_action( dtw->viewwidget.view ); + if ( act ) { + sp_action_set_sensitive( act, enabled ); + } + } + gtk_widget_set_sensitive( dtw->cms_adjust, enabled ); } void @@ -758,7 +889,7 @@ SPDesktopWidget::shutdown() if (inkscape_is_sole_desktop_for_document(*desktop)) { SPDocument *doc = desktop->doc(); - if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL) { + if (doc->isModifiedSinceSave()) { GtkWidget *dialog; /** \todo @@ -772,7 +903,7 @@ SPDesktopWidget::shutdown() GTK_BUTTONS_NONE, _("Save changes to document \"%s\" before closing?\n\n" "If you close without saving, your changes will be discarded."), - SP_DOCUMENT_NAME(doc)); + doc->getName()); // fix for bug 1767940: GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(GTK_MESSAGE_DIALOG(dialog)->label), GTK_CAN_FOCUS); @@ -794,11 +925,12 @@ SPDesktopWidget::shutdown() { Gtk::Window *window = (Gtk::Window*)gtk_object_get_data (GTK_OBJECT(this), "window"); - sp_document_ref(doc); + doc->doRef(); + sp_namedview_document_from_window(desktop); if (sp_file_save_document(*window, doc)) { - sp_document_unref(doc); + doc->doUnref(); } else { // save dialog cancelled or save failed - sp_document_unref(doc); + doc->doUnref(); return TRUE; } @@ -813,7 +945,7 @@ SPDesktopWidget::shutdown() } /* Code to check data loss */ bool allow_data_loss = FALSE; - while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE) { + while (doc->getReprRoot()->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE) { GtkWidget *dialog; /** \todo @@ -826,19 +958,22 @@ SPDesktopWidget::shutdown() GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, _("The file \"%s\" was saved with a format (%s) that may cause data loss!\n\n" - "Do you want to save this file in another format?"), - SP_DOCUMENT_NAME(doc), - Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name()); + "Do you want to save this file as Inkscape SVG?"), + doc->getName() ? doc->getName() : "Unnamed", + SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE); // fix for bug 1767940: GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(GTK_MESSAGE_DIALOG(dialog)->label), GTK_CAN_FOCUS); GtkWidget *close_button; close_button = gtk_button_new_with_mnemonic(_("Close _without saving")); gtk_widget_show(close_button); + GtkWidget *save_button; + save_button = gtk_button_new_with_mnemonic(_("_Save as SVG")); + gtk_widget_show(save_button); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), close_button, GTK_RESPONSE_NO); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, GTK_RESPONSE_YES); + gtk_dialog_add_action_widget(GTK_DIALOG(dialog), save_button, GTK_RESPONSE_YES); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES); gint response; @@ -848,14 +983,14 @@ SPDesktopWidget::shutdown() switch (response) { case GTK_RESPONSE_YES: { - sp_document_ref(doc); + doc->doRef(); Gtk::Window *window = (Gtk::Window*)gtk_object_get_data (GTK_OBJECT(this), "window"); - if (sp_file_save_dialog(*window, doc)) { - sp_document_unref(doc); + if (sp_file_save_dialog(*window, doc, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG)) { + doc->doUnref(); } else { // save dialog cancelled or save failed - sp_document_unref(doc); + doc->doUnref(); return TRUE; } @@ -876,20 +1011,21 @@ SPDesktopWidget::shutdown() * But we save the info here regardless of the setting. */ { - gint full = desktop->is_fullscreen() ? 1 : 0; - gint maxed = desktop->is_maximized() ? 1 : 0; - prefs_set_int_attribute("desktop.geometry", "fullscreen", full); - prefs_set_int_attribute("desktop.geometry", "maximized", maxed); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool maxed = desktop->is_maximized(); + bool full = desktop->is_fullscreen(); + prefs->setBool("/desktop/geometry/fullscreen", full); + prefs->setBool("/desktop/geometry/maximized", maxed); gint w, h, x, y; desktop->getWindowGeometry(x, y, w, h); // Don't save geom for maximized windows. It // just tells you the current maximized size, which is not // as useful as whatever value it had previously. if (!maxed && !full) { - prefs_set_int_attribute("desktop.geometry", "width", w); - prefs_set_int_attribute("desktop.geometry", "height", h); - prefs_set_int_attribute("desktop.geometry", "x", x); - prefs_set_int_attribute("desktop.geometry", "y", y); + prefs->setInt("/desktop/geometry/width", w); + prefs->setInt("/desktop/geometry/height", h); + prefs->setInt("/desktop/geometry/x", x); + prefs->setInt("/desktop/geometry/y", y); } } @@ -936,14 +1072,14 @@ SPDesktopWidget::disableInteraction() } void -SPDesktopWidget::setCoordinateStatus(NR::Point p) +SPDesktopWidget::setCoordinateStatus(Geom::Point p) { gchar *cstr; - cstr = g_strdup_printf("%7.2f ", dt2r * p[NR::X]); + cstr = g_strdup_printf("%7.2f ", dt2r * p[Geom::X]); gtk_label_set_markup( GTK_LABEL(this->coord_status_x), cstr ); g_free(cstr); - cstr = g_strdup_printf("%7.2f ", dt2r * p[NR::Y]); + cstr = g_strdup_printf("%7.2f ", dt2r * p[Geom::Y]); gtk_label_set_markup( GTK_LABEL(this->coord_status_y), cstr ); g_free(cstr); } @@ -971,13 +1107,13 @@ SPDesktopWidget::getWindowGeometry (gint &x, gint &y, gint &w, gint &h) } void -SPDesktopWidget::setWindowPosition (NR::Point p) +SPDesktopWidget::setWindowPosition (Geom::Point p) { Gtk::Window *window = (Gtk::Window*)gtk_object_get_data (GTK_OBJECT(this), "window"); if (window) { - window->move (gint(round(p[NR::X])), gint(round(p[NR::Y]))); + window->move (gint(round(p[Geom::X])), gint(round(p[Geom::Y]))); } } @@ -1002,9 +1138,10 @@ SPDesktopWidget::setWindowSize (gint w, gint h) void SPDesktopWidget::setWindowTransient (void *p, int transient_policy) { - GtkWindow *w =GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(this))); - if (w) + Gtk::Window *window = (Gtk::Window*)gtk_object_get_data (GTK_OBJECT(this), "window"); + if (window) { + GtkWindow *w = (GtkWindow *) window->gobj(); gtk_window_set_transient_for (GTK_WINDOW(p), w); /* @@ -1015,7 +1152,6 @@ SPDesktopWidget::setWindowTransient (void *p, int transient_policy) * (so that its transients also could raise) */ if (transient_policy == 2) - // without this, a transient window not always emerges on top gtk_window_present (w); } @@ -1075,12 +1211,13 @@ sp_desktop_widget_maximize(SPDesktopWidget *dtw) // a separate non-maximized size. if (!dtw->desktop->is_iconified() && !dtw->desktop->is_fullscreen()) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint w, h, x, y; dtw->getWindowGeometry(x, y, w, h); - prefs_set_int_attribute("desktop.geometry", "width", w); - prefs_set_int_attribute("desktop.geometry", "height", h); - prefs_set_int_attribute("desktop.geometry", "x", x); - prefs_set_int_attribute("desktop.geometry", "y", y); + prefs->setInt("/desktop/geometry/width", w); + prefs->setInt("/desktop/geometry/height", h); + prefs->setInt("/desktop/geometry/x", x); + prefs->setInt("/desktop/geometry/y", y); } gtk_window_maximize(topw); } @@ -1102,12 +1239,13 @@ sp_desktop_widget_fullscreen(SPDesktopWidget *dtw) // a separate non-maximized size. if (!dtw->desktop->is_iconified() && !dtw->desktop->is_maximized()) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint w, h, x, y; dtw->getWindowGeometry(x, y, w, h); - prefs_set_int_attribute("desktop.geometry", "width", w); - prefs_set_int_attribute("desktop.geometry", "height", h); - prefs_set_int_attribute("desktop.geometry", "x", x); - prefs_set_int_attribute("desktop.geometry", "y", y); + prefs->setInt("/desktop/geometry/width", w); + prefs->setInt("/desktop/geometry/height", h); + prefs->setInt("/desktop/geometry/x", x); + prefs->setInt("/desktop/geometry/y", y); } gtk_window_fullscreen(topw); // widget layout is triggered by the resulting window_state_event @@ -1119,50 +1257,67 @@ sp_desktop_widget_fullscreen(SPDesktopWidget *dtw) /** * Hide whatever the user does not want to see in the window */ -void -sp_desktop_widget_layout (SPDesktopWidget *dtw) +void SPDesktopWidget::layoutWidgets() { - bool fullscreen = dtw->desktop->is_fullscreen(); + SPDesktopWidget *dtw = this; + Glib::ustring pref_root; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + if (dtw->desktop->is_focusMode()) { + pref_root = "/focus/"; + } else if (dtw->desktop->is_fullscreen()) { + pref_root = "/fullscreen/"; + } else { + pref_root = "/window/"; + } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.menu" : "window.menu", "state", 1) == 0) { +#ifndef GDK_WINDOWING_QUARTZ + if (!prefs->getBool(pref_root + "menu/state", true)) { gtk_widget_hide_all (dtw->menubar); } else { gtk_widget_show_all (dtw->menubar); } +#endif - if (prefs_get_int_attribute (fullscreen ? "fullscreen.commands" : "window.commands", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "commands/state", true)) { gtk_widget_hide_all (dtw->commands_toolbox); } else { gtk_widget_show_all (dtw->commands_toolbox); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.toppanel" : "window.toppanel", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "snaptoolbox/state", true)) { + gtk_widget_hide_all (dtw->snap_toolbox); + } else { + gtk_widget_show_all (dtw->snap_toolbox); + } + + if (!prefs->getBool(pref_root + "toppanel/state", true)) { gtk_widget_hide_all (dtw->aux_toolbox); } else { // we cannot just show_all because that will show all tools' panels; // this is a function from toolbox.cpp that shows only the current tool's panel - show_aux_toolbox (dtw->aux_toolbox); + ToolboxFactory::showAuxToolbox(dtw->aux_toolbox); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.toolbox" : "window.toolbox", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "toolbox/state", true)) { gtk_widget_hide_all (dtw->tool_toolbox); } else { gtk_widget_show_all (dtw->tool_toolbox); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.statusbar" : "window.statusbar", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "statusbar/state", true)) { gtk_widget_hide_all (dtw->statusbar); } else { gtk_widget_show_all (dtw->statusbar); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.panels" : "window.panels", "state", 1) == 0) { - gtk_widget_hide_all( dtw->panels ); + if (!prefs->getBool(pref_root + "panels/state", true)) { + gtk_widget_hide_all( GTK_WIDGET(dtw->panels->gobj()) ); } else { - gtk_widget_show_all( dtw->panels ); + gtk_widget_show_all( GTK_WIDGET(dtw->panels->gobj()) ); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "scrollbars/state", true)) { gtk_widget_hide_all (dtw->hscrollbar); gtk_widget_hide_all (dtw->vscrollbar_box); gtk_widget_hide_all( dtw->cms_adjust ); @@ -1172,7 +1327,7 @@ sp_desktop_widget_layout (SPDesktopWidget *dtw) gtk_widget_show_all( dtw->cms_adjust ); } - if (prefs_get_int_attribute (fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1) == 0) { + if (!prefs->getBool(pref_root + "rulers/state", true)) { gtk_widget_hide_all (dtw->hruler); gtk_widget_hide_all (dtw->vruler); } else { @@ -1194,11 +1349,19 @@ SPDesktopWidget::setToolboxFocusTo (const gchar* label) void SPDesktopWidget::setToolboxAdjustmentValue (gchar const *id, double value) { + GtkAdjustment *a = NULL; gpointer hb = sp_search_by_data_recursive (aux_toolbox, (gpointer) id); - if (hb && GTK_IS_WIDGET(hb) && GTK_IS_SPIN_BUTTON(hb)) { - GtkAdjustment *a = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(hb)); - gtk_adjustment_set_value (a, value); + if (hb && GTK_IS_WIDGET(hb)) { + if (GTK_IS_SPIN_BUTTON(hb)) + a = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(hb)); + else if (GTK_IS_RANGE(hb)) + a = gtk_range_get_adjustment (GTK_RANGE(hb)); } + + if (a) + gtk_adjustment_set_value (a, value); + else + g_warning ("Could not find GtkAdjustment for %s\n", id); } void @@ -1231,19 +1394,65 @@ SPDesktopWidget::isToolboxButtonActive (const gchar* id) return isActive; } -SPViewWidget * -sp_desktop_widget_new (SPNamedView *namedview) +void SPDesktopWidget::setToolboxPosition(Glib::ustring const& id, GtkPositionType pos) { - SPDesktopWidget *dtw = (SPDesktopWidget*)gtk_type_new (SP_TYPE_DESKTOP_WIDGET); + // Note - later on these won't be individual member variables. + GtkWidget* toolbox = 0; + if (id == "ToolToolbar") { + toolbox = tool_toolbox; + } else if (id == "AuxToolbar") { + toolbox = aux_toolbox; + } else if (id == "CommandsToolbar") { + toolbox = commands_toolbox; + } else if (id == "SnapToolbar") { + toolbox = snap_toolbox; + } + + + if (toolbox) { + switch(pos) { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + if ( gtk_widget_is_ancestor(toolbox, hbox) ) { + gtk_widget_reparent( toolbox, vbox ); + gtk_box_set_child_packing(GTK_BOX(vbox), toolbox, FALSE, TRUE, 0, GTK_PACK_START); + } + ToolboxFactory::setOrientation(toolbox, GTK_ORIENTATION_HORIZONTAL); + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + if ( !gtk_widget_is_ancestor(toolbox, hbox) ) { + gtk_widget_reparent( toolbox, hbox ); + gtk_box_set_child_packing(GTK_BOX(hbox), toolbox, FALSE, TRUE, 0, GTK_PACK_START); + if (pos == GTK_POS_LEFT) { + gtk_box_reorder_child( GTK_BOX(hbox), toolbox, 0 ); + } + } + ToolboxFactory::setOrientation(toolbox, GTK_ORIENTATION_VERTICAL); + break; + } + } +} + + +SPViewWidget *sp_desktop_widget_new( SPNamedView *namedview ) +{ + SPDesktopWidget* dtw = SPDesktopWidget::createInstance(namedview); + + return SP_VIEW_WIDGET(dtw); +} + +SPDesktopWidget* SPDesktopWidget::createInstance(SPNamedView *namedview) +{ + SPDesktopWidget *dtw = (SPDesktopWidget*)g_object_new(SP_TYPE_DESKTOP_WIDGET, NULL); dtw->dt2r = 1.0 / namedview->doc_units->unittobase; - dtw->ruler_origin = NR::Point(0,0); //namedview->gridorigin; Why was the grid origin used here? + dtw->ruler_origin = Geom::Point(0,0); //namedview->gridorigin; Why was the grid origin used here? dtw->desktop = new SPDesktop(); dtw->stub = new SPDesktopWidget::WidgetStub (dtw); - dtw->desktop->registerEditWidget (dtw->stub); - dtw->desktop->init (namedview, dtw->canvas); + dtw->desktop->init (namedview, dtw->canvas, dtw->stub); inkscape_add_desktop (dtw->desktop); // Add the shape geometry to libavoid for autorouting connectors. @@ -1258,64 +1467,134 @@ sp_desktop_widget_new (SPNamedView *namedview) sp_view_widget_set_view (SP_VIEW_WIDGET (dtw), dtw->desktop); /* Listen on namedview modification */ - dtw->modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_desktop_widget_namedview_modified), dtw)); + dtw->modified_connection = namedview->connectModified(sigc::mem_fun(*dtw, &SPDesktopWidget::namedviewModified)); dtw->layer_selector->setDesktop(dtw->desktop); dtw->menubar = sp_ui_main_menubar (dtw->desktop); +#ifndef GDK_WINDOWING_QUARTZ gtk_widget_show_all (dtw->menubar); gtk_box_pack_start (GTK_BOX (dtw->vbox), dtw->menubar, FALSE, FALSE, 0); +#endif + + dtw->layoutWidgets(); - sp_desktop_widget_layout (dtw); + std::vector toolboxes; + toolboxes.push_back(dtw->tool_toolbox); + toolboxes.push_back(dtw->aux_toolbox); + toolboxes.push_back(dtw->commands_toolbox); + toolboxes.push_back(dtw->snap_toolbox); - sp_tool_toolbox_set_desktop (dtw->tool_toolbox, dtw->desktop); - sp_aux_toolbox_set_desktop (dtw->aux_toolbox, dtw->desktop); - sp_commands_toolbox_set_desktop (dtw->commands_toolbox, dtw->desktop); + dtw->panels->setDesktop( dtw->desktop ); - return SP_VIEW_WIDGET (dtw); + UXManager::getInstance()->addTrack(dtw); + UXManager::getInstance()->connectToDesktop( toolboxes, dtw->desktop ); + + return dtw; } void -SPDesktopWidget::viewSetPosition (NR::Point p) +SPDesktopWidget::viewSetPosition (Geom::Point p) { - NR::Point const origin = ( p - ruler_origin ); + Geom::Point const origin = ( p - ruler_origin ); /// \todo fixme: - GTK_RULER(hruler)->position = origin[NR::X]; + GTK_RULER(hruler)->position = origin[Geom::X]; gtk_ruler_draw_pos (GTK_RULER (hruler)); - GTK_RULER(vruler)->position = origin[NR::Y]; + GTK_RULER(vruler)->position = origin[Geom::Y]; gtk_ruler_draw_pos (GTK_RULER (vruler)); } void sp_desktop_widget_update_rulers (SPDesktopWidget *dtw) { - NR::Rect const viewbox = dtw->canvas->getViewbox(); + sp_desktop_widget_update_hruler(dtw); + sp_desktop_widget_update_vruler(dtw); +} + +void +sp_desktop_widget_update_hruler (SPDesktopWidget *dtw) +{ + /* The viewbox (in integers) must exactly match the size of SPCanvasbuf's pixel buffer. + * This is important because the former is being used for drawing the ruler, whereas + * the latter is used for drawing e.g. the grids and guides. Only when the viewbox + * coincides with the pixel buffer, everything will line up nicely. + */ + NR::IRect viewbox = dtw->canvas->getViewboxIntegers(); + double const scale = dtw->desktop->current_zoom(); - double s = viewbox.min()[NR::X] / scale - dtw->ruler_origin[NR::X]; - double e = viewbox.max()[NR::X] / scale - dtw->ruler_origin[NR::X]; + double s = viewbox.min()[Geom::X] / scale - dtw->ruler_origin[Geom::X]; + double e = viewbox.max()[Geom::X] / scale - dtw->ruler_origin[Geom::X]; gtk_ruler_set_range(GTK_RULER(dtw->hruler), s, e, GTK_RULER(dtw->hruler)->position, (e - s)); - s = viewbox.min()[NR::Y] / -scale - dtw->ruler_origin[NR::Y]; - e = viewbox.max()[NR::Y] / -scale - dtw->ruler_origin[NR::Y]; +} + +void +sp_desktop_widget_update_vruler (SPDesktopWidget *dtw) +{ + /* The viewbox (in integers) must exactly match the size of SPCanvasbuf's pixel buffer. + * This is important because the former is being used for drawing the ruler, whereas + * the latter is used for drawing e.g. the grids and guides. Only when the viewbox + * coincides with the pixel buffer, everything will line up nicely. + */ + NR::IRect viewbox = dtw->canvas->getViewboxIntegers(); + + double const scale = dtw->desktop->current_zoom(); + double s = viewbox.min()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; + double e = viewbox.max()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y]; gtk_ruler_set_range(GTK_RULER(dtw->vruler), s, e, GTK_RULER(dtw->vruler)->position, (e - s)); } -static void -sp_desktop_widget_namedview_modified (SPObject *obj, guint flags, SPDesktopWidget *dtw) +void SPDesktopWidget::namedviewModified(SPObject *obj, guint flags) { SPNamedView *nv=SP_NAMEDVIEW(obj); - if (flags & SP_OBJECT_MODIFIED_FLAG) { - dtw->dt2r = 1.0 / nv->doc_units->unittobase; - dtw->ruler_origin = NR::Point(0,0); //nv->gridorigin; Why was the grid origin used here? - sp_ruler_set_metric (GTK_RULER (dtw->vruler), nv->getDefaultMetric()); - sp_ruler_set_metric (GTK_RULER (dtw->hruler), nv->getDefaultMetric()); - - gtk_tooltips_set_tip (dtw->tt, dtw->hruler_box, gettext(sp_unit_get_plural (nv->doc_units)), NULL); - gtk_tooltips_set_tip (dtw->tt, dtw->vruler_box, gettext(sp_unit_get_plural (nv->doc_units)), NULL); - - sp_desktop_widget_update_rulers (dtw); + if (flags & SP_OBJECT_MODIFIED_FLAG) { + this->dt2r = 1.0 / nv->doc_units->unittobase; + this->ruler_origin = Geom::Point(0,0); //nv->gridorigin; Why was the grid origin used here? + + sp_ruler_set_metric(GTK_RULER (this->vruler), nv->getDefaultMetric()); + sp_ruler_set_metric(GTK_RULER (this->hruler), nv->getDefaultMetric()); + + /* This loops through all the grandchildren of aux toolbox, + * and for each that it finds, it performs an sp_search_by_data_recursive(), + * looking for widgets that hold some "tracker" data (this is used by + * all toolboxes to refer to the unit selector). The default document units + * is then selected within these unit selectors. + * + * Of course it would be nice to be able to refer to the toolbox and the + * unit selector directly by name, but I don't yet see a way to do that. + * + * This should solve: https://bugs.launchpad.net/inkscape/+bug/362995 + */ + if (GTK_IS_CONTAINER(aux_toolbox)) { + GList *ch = gtk_container_get_children (GTK_CONTAINER(aux_toolbox)); + for (GList *i = ch; i != NULL; i = i->next) { + if (GTK_IS_CONTAINER(i->data)) { + GList *grch = gtk_container_get_children (GTK_CONTAINER(i->data)); + for (GList *j = grch; j != NULL; j = j->next) { + if (!GTK_IS_WIDGET(j->data)) // wasn't a widget + continue; + + gpointer t = sp_search_by_data_recursive(GTK_WIDGET(j->data), (gpointer) "tracker"); + if (t == NULL) // didn't find any tracker data + continue; + + UnitTracker *tracker = reinterpret_cast( t ); + if (tracker == NULL) // it's null when inkscape is first opened + continue; + + tracker->setActiveUnit( nv->doc_units ); + } // grandchildren + } // if child is a container + } // children + } // if aux_toolbox is a container + + gtk_tooltips_set_tip(this->tt, this->hruler_box, gettext(sp_unit_get_plural (nv->doc_units)), NULL); + gtk_tooltips_set_tip(this->tt, this->vruler_box, gettext(sp_unit_get_plural (nv->doc_units)), NULL); + + sp_desktop_widget_update_rulers(this); + ToolboxFactory::updateSnapToolbox(this->desktop, 0, this->snap_toolbox); } } @@ -1330,12 +1609,24 @@ sp_desktop_widget_adjustment_value_changed (GtkAdjustment */*adj*/, SPDesktopWid sp_canvas_scroll_to (dtw->canvas, dtw->hadj->value, dtw->vadj->value, FALSE); sp_desktop_widget_update_rulers (dtw); + /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ + sp_box3d_context_update_lines(dtw->desktop->event_context); + dtw->update = 0; } /* we make the desktop window with focus active, signal is connected in interface.c */ bool SPDesktopWidget::onFocusInEvent(GdkEventFocus*) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/options/bitmapautoreload/value", true)) { + GSList const *imageList = (desktop->doc())->getResourceList("image"); + for (GSList const *p = imageList; p; p = p->next) { + SPImage* image = SP_IMAGE(p->data); + sp_image_refresh_if_outdated( image ); + } + } + inkscape_activate_desktop (desktop); return false; @@ -1391,9 +1682,9 @@ sp_dtw_zoom_value_changed (GtkSpinButton *spin, gpointer data) SPDesktopWidget *dtw = SP_DESKTOP_WIDGET (data); SPDesktop *desktop = dtw->desktop; - NR::Rect const d = desktop->get_display_area(); + Geom::Rect const d = desktop->get_display_area(); g_signal_handler_block (spin, dtw->zoom_update); - desktop->zoom_absolute (d.midpoint()[NR::X], d.midpoint()[NR::Y], zoom_factor); + desktop->zoom_absolute (d.midpoint()[Geom::X], d.midpoint()[Geom::Y], zoom_factor); g_signal_handler_unblock (spin, dtw->zoom_update); spinbutton_defocus (GTK_OBJECT (spin)); @@ -1446,8 +1737,8 @@ sp_dtw_zoom_populate_popup (GtkEntry */*entry*/, GtkMenu *menu, gpointer data) static void sp_dtw_zoom_menu_handler (SPDesktop *dt, gdouble factor) { - NR::Rect const d = dt->get_display_area(); - dt->zoom_absolute(d.midpoint()[NR::X], d.midpoint()[NR::Y], factor); + Geom::Rect const d = dt->get_display_area(); + dt->zoom_absolute(d.midpoint()[Geom::X], d.midpoint()[Geom::Y], factor); } static void @@ -1486,6 +1777,13 @@ sp_dtw_zoom_selection (GtkMenuItem */*item*/, gpointer data) static_cast(data)->zoom_selection(); } +static void +sp_dtw_sticky_zoom_toggled (GtkMenuItem *, gpointer data) +{ + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(data); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/stickyzoom/value", SP_BUTTON_IS_DOWN(dtw->sticky_zoom)); +} void @@ -1502,30 +1800,44 @@ sp_desktop_widget_update_zoom (SPDesktopWidget *dtw) void sp_desktop_widget_toggle_rulers (SPDesktopWidget *dtw) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (GTK_WIDGET_VISIBLE (dtw->hruler)) { gtk_widget_hide_all (dtw->hruler); gtk_widget_hide_all (dtw->vruler); - prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 0); + prefs->setBool(dtw->desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", false); } else { gtk_widget_show_all (dtw->hruler); gtk_widget_show_all (dtw->vruler); - prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 1); + prefs->setBool(dtw->desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", true); } } void sp_desktop_widget_toggle_scrollbars (SPDesktopWidget *dtw) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (GTK_WIDGET_VISIBLE (dtw->hscrollbar)) { gtk_widget_hide_all (dtw->hscrollbar); gtk_widget_hide_all (dtw->vscrollbar_box); gtk_widget_hide_all( dtw->cms_adjust ); - prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0); + prefs->setBool(dtw->desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", false); } else { gtk_widget_show_all (dtw->hscrollbar); gtk_widget_show_all (dtw->vscrollbar_box); gtk_widget_show_all( dtw->cms_adjust ); - prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1); + prefs->setBool(dtw->desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", true); + } +} + +void sp_desktop_widget_toggle_color_prof_adj( SPDesktopWidget *dtw ) +{ + + if ( GTK_WIDGET_SENSITIVE( dtw->cms_adjust ) ) { + if ( SP_BUTTON_IS_DOWN(dtw->cms_adjust) ) { + sp_button_toggle_set_down( SP_BUTTON(dtw->cms_adjust), FALSE ); + } else { + sp_button_toggle_set_down( SP_BUTTON(dtw->cms_adjust), TRUE ); + } } } @@ -1533,12 +1845,13 @@ sp_desktop_widget_toggle_scrollbars (SPDesktopWidget *dtw) void sp_spw_toggle_menubar (SPDesktopWidget *dtw, bool is_fullscreen) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (GTK_WIDGET_VISIBLE (dtw->menubar)) { gtk_widget_hide_all (dtw->menubar); - prefs_set_int_attribute (is_fullscreen ? "fullscreen.menu" : "window.menu", "state", 0); + prefs->setBool(is_fullscreen ? "/fullscreen/menu/state" : "/window/menu/state", false); } else { gtk_widget_show_all (dtw->menubar); - prefs_set_int_attribute (is_fullscreen ? "fullscreen.menu" : "window.menu", "state", 1); + prefs->setBool(is_fullscreen ? "/fullscreen/menu/state" : "/window/menu/state", true); } } */ @@ -1569,32 +1882,32 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) /* The desktop region we always show unconditionally */ SPDocument *doc = dtw->desktop->doc(); - NR::Rect darea(NR::Point(-sp_document_width(doc), -sp_document_height(doc)), - NR::Point(2 * sp_document_width(doc), 2 * sp_document_height(doc))); - darea = NR::union_bounds(darea, sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)))); + Geom::Rect darea ( Geom::Point(-doc->getWidth(), -doc->getHeight()), + Geom::Point(2 * doc->getWidth(), 2 * doc->getHeight()) ); + SPObject* root = doc->root; + SPItem* item = SP_ITEM(root); + Geom::OptRect deskarea = Geom::unify(darea, item->getBboxDesktop()); /* Canvas region we always show unconditionally */ - NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64, - darea.max()[NR::Y] * -scale - 64), - NR::Point(darea.max()[NR::X] * scale + 64, - darea.min()[NR::Y] * -scale + 64)); + Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64), + Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) ); - NR::Rect viewbox = dtw->canvas->getViewbox(); + Geom::Rect viewbox = dtw->canvas->getViewbox(); /* Viewbox is always included into scrollable region */ - carea = NR::union_bounds(carea, viewbox); - - set_adjustment(dtw->hadj, carea.min()[NR::X], carea.max()[NR::X], - viewbox.dimensions()[NR::X], - 0.1 * viewbox.dimensions()[NR::X], - viewbox.dimensions()[NR::X]); - gtk_adjustment_set_value(dtw->hadj, viewbox.min()[NR::X]); - - set_adjustment(dtw->vadj, carea.min()[NR::Y], carea.max()[NR::Y], - viewbox.dimensions()[NR::Y], - 0.1 * viewbox.dimensions()[NR::Y], - viewbox.dimensions()[NR::Y]); - gtk_adjustment_set_value(dtw->vadj, viewbox.min()[NR::Y]); + carea = Geom::unify(carea, viewbox); + + set_adjustment(dtw->hadj, carea.min()[Geom::X], carea.max()[Geom::X], + viewbox.dimensions()[Geom::X], + 0.1 * viewbox.dimensions()[Geom::X], + viewbox.dimensions()[Geom::X]); + gtk_adjustment_set_value(dtw->hadj, viewbox.min()[Geom::X]); + + set_adjustment(dtw->vadj, carea.min()[Geom::Y], carea.max()[Geom::Y], + viewbox.dimensions()[Geom::Y], + 0.1 * viewbox.dimensions()[Geom::Y], + viewbox.dimensions()[Geom::Y]); + gtk_adjustment_set_value(dtw->vadj, viewbox.min()[Geom::Y]); dtw->update = 0; }