diff options
| author | Richard White <rwhite8282@gmail.com> | 2016-05-19 01:17:29 +0000 |
|---|---|---|
| committer | Richard White <rwhite8282@gmail.com> | 2016-05-19 01:17:29 +0000 |
| commit | 1fe9c2603c33fddcd9f2688b30e843f91e1a86fa (patch) | |
| tree | 13289cbe033a46a40eb829437e115b5393e2ca84 /src/widgets | |
| parent | Corrected frame extension stroke and fill values on 64 bit machine. (diff) | |
| parent | GTK3: Another widget named. (diff) | |
| download | inkscape-1fe9c2603c33fddcd9f2688b30e843f91e1a86fa.tar.gz inkscape-1fe9c2603c33fddcd9f2688b30e843f91e1a86fa.zip | |
Merge from Inkscape trunk.
(bzr r14668.1.3)
Diffstat (limited to 'src/widgets')
25 files changed, 2338 insertions, 577 deletions
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index c38bde5cf..225afe317 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -38,7 +38,6 @@ set(widgets_SRC paint-selector.cpp ruler.cpp select-toolbar.cpp - shrink-wrap-button.cpp sp-attribute-widget.cpp sp-color-selector.cpp sp-widget.cpp @@ -94,7 +93,6 @@ set(widgets_SRC paint-selector.h ruler.h select-toolbar.h - shrink-wrap-button.h sp-attribute-widget.h sp-color-selector.h sp-widget.h @@ -110,6 +108,11 @@ set(widgets_SRC widget-sizes.h ) +if(${WITH_GTK3_EXPERIMENTAL}) + set(image_menu_item_SRC image-menu-item.h image-menu-item.c) + add_inkscape_source("${image_menu_item_SRC}") +endif() + # add_inkscape_lib(widgets_LIB "${widgets_SRC}") add_inkscape_source("${widgets_SRC}") @@ -121,3 +124,6 @@ set ( widgets_paintbucket_SRC if ("${HAVE_POTRACE}") add_inkscape_source("${widgets_paintbucket_SRC}") endif() + + + diff --git a/src/widgets/Makefile_insert b/src/widgets/Makefile_insert index 6913f4a58..c9f04de14 100644 --- a/src/widgets/Makefile_insert +++ b/src/widgets/Makefile_insert @@ -1,5 +1,11 @@ ## Makefile.am fragment sourced by src/Makefile.am. +if WITH_GTKMM_3_0 +ink_common_sources += \ + widgets/image-menu-item.c \ + widgets/image-menu-item.h +endif + ink_common_sources += \ widgets/arc-toolbar.cpp \ widgets/arc-toolbar.h \ @@ -66,8 +72,6 @@ ink_common_sources += \ widgets/ruler.h \ widgets/select-toolbar.cpp \ widgets/select-toolbar.h \ - widgets/shrink-wrap-button.cpp \ - widgets/shrink-wrap-button.h \ widgets/spray-toolbar.cpp \ widgets/spray-toolbar.h \ widgets/spiral-toolbar.cpp \ diff --git a/src/widgets/button.cpp b/src/widgets/button.cpp index 1776e28c4..6ea8c1360 100644 --- a/src/widgets/button.cpp +++ b/src/widgets/button.cpp @@ -96,7 +96,6 @@ static void sp_button_dispose(GObject *object) static void sp_button_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width) { GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); - GtkStyle *style = gtk_widget_get_style(widget); if (child) { gtk_widget_get_preferred_width(GTK_WIDGET(child), minimal_width, natural_width); @@ -105,14 +104,20 @@ static void sp_button_get_preferred_width(GtkWidget *widget, gint *minimal_width *natural_width = 0; } - *minimal_width += 2 + 2 * MAX(2, style->xthickness); - *natural_width += 2 + 2 * MAX(2, style->xthickness); + GtkStyleContext *context = gtk_widget_get_style_context (widget); + GtkBorder padding; + GtkBorder border; + + gtk_style_context_get_padding(context, GTK_STATE_FLAG_NORMAL, &padding); + gtk_style_context_get_border( context, GTK_STATE_FLAG_NORMAL, &border ); + + *minimal_width += MAX(2, padding.left + padding.right + border.left + border.right); + *natural_width += MAX(2, padding.left + padding.right + border.left + border.right); } static void sp_button_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height) { GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); - GtkStyle *style = gtk_widget_get_style(widget); if (child) { gtk_widget_get_preferred_height(GTK_WIDGET(child), minimal_height, natural_height); @@ -121,8 +126,15 @@ static void sp_button_get_preferred_height(GtkWidget *widget, gint *minimal_heig *natural_height = 0; } - *minimal_height += 2 + 2 * MAX(2, style->ythickness); - *natural_height += 2 + 2 * MAX(2, style->ythickness); + GtkStyleContext *context = gtk_widget_get_style_context (widget); + GtkBorder padding; + GtkBorder border; + + gtk_style_context_get_padding(context, GTK_STATE_FLAG_NORMAL, &padding); + gtk_style_context_get_border( context, GTK_STATE_FLAG_NORMAL, &border ); + + *minimal_height += MAX(2, padding.top + padding.bottom + border.top + border.bottom); + *natural_height += MAX(2, padding.top + padding.bottom + border.top + border.bottom); } #else static void sp_button_size_request(GtkWidget *widget, GtkRequisition *requisition) diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 1fdd3ca6d..0cee426b6 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -249,7 +249,7 @@ SPDesktopWidget::setMessage (Inkscape::MessageType type, const gchar *message) gdk_window_process_updates(gtk_widget_get_window(GTK_WIDGET(sb)), TRUE); } - gtk_widget_set_tooltip_text (this->select_status_eventbox, gtk_label_get_text (sb)); + gtk_widget_set_tooltip_text (this->select_status, gtk_label_get_text (sb)); } Geom::Point @@ -346,6 +346,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) /* Main table */ #if GTK_CHECK_VERSION(3,0,0) dtw->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(dtw->vbox, "DesktopMainTable"); #else dtw->vbox = gtk_vbox_new (FALSE, 0); #endif @@ -353,6 +354,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(dtw->statusbar, "DesktopStatusBar"); #else dtw->statusbar = gtk_hbox_new (FALSE, 0); #endif @@ -364,7 +366,6 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/); dtw->panels->setOrientation(SP_ANCHOR_SOUTH); - #if GTK_CHECK_VERSION(3,0,0) dtw->panels->set_vexpand(false); #endif @@ -374,6 +375,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(dtw->hbox, "DesktopHbox"); #else dtw->hbox = gtk_hbox_new(FALSE, 0); #endif @@ -404,6 +406,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) Glib::RefPtr<Gtk::CssProvider> guides_lock_style_provider = Gtk::CssProvider::create(); guides_lock_style_provider->load_from_data("GtkWidget { padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; }"); Gtk::Widget * wnd = Glib::wrap(dtw->guides_lock); + wnd->set_name("LockGuides"); Glib::RefPtr<Gtk::StyleContext> context = wnd->get_style_context(); context->add_provider(guides_lock_style_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); #endif @@ -411,6 +414,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) /* Horizontal ruler */ GtkWidget *eventbox = gtk_event_box_new (); dtw->hruler = sp_ruler_new(GTK_ORIENTATION_HORIZONTAL); + gtk_widget_set_name(dtw->hruler, "HorizontalRuler"); dtw->hruler_box = eventbox; Inkscape::Util::Unit const *pt = unit_table.getUnit("pt"); sp_ruler_set_unit(SP_RULER(dtw->hruler), pt); @@ -421,13 +425,15 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) g_signal_connect (G_OBJECT (eventbox), "motion_notify_event", G_CALLBACK (sp_dt_hruler_event), dtw); #if GTK_CHECK_VERSION(3,0,0) - GtkWidget *tbl = gtk_grid_new(); + GtkWidget *tbl_wrapper = gtk_grid_new(); // Is this widget really needed? + gtk_widget_set_name(tbl_wrapper, "CanvasTableWrapper"); dtw->canvas_tbl = gtk_grid_new(); + gtk_widget_set_name(dtw->canvas_tbl, "CanvasTable"); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->guides_lock, 0, 0, 1, 1); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), eventbox, 1, 0, 1, 1); #else - GtkWidget *tbl = gtk_table_new(2, 3, FALSE); + GtkWidget *tbl_wrapper = gtk_table_new(2, 3, FALSE); dtw->canvas_tbl = gtk_table_new(3, 3, FALSE); gtk_table_attach(GTK_TABLE(dtw->canvas_tbl), @@ -442,11 +448,12 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) 0, 0); #endif g_signal_connect (G_OBJECT (dtw->guides_lock), "toggled", G_CALLBACK (sp_update_guides_lock), dtw); - gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl, TRUE, TRUE, 1 ); + gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl_wrapper, TRUE, TRUE, 1 ); /* Vertical ruler */ eventbox = gtk_event_box_new (); dtw->vruler = sp_ruler_new(GTK_ORIENTATION_VERTICAL); + gtk_widget_set_name(dtw->vruler, "VerticalRuler"); /* Vertical ruler */ dtw->vruler_box = eventbox; @@ -471,11 +478,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) // Horizontal scrollbar dtw->hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0)); - - - #if GTK_CHECK_VERSION(3,0,0) dtw->hscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (dtw->hadj)); + gtk_widget_set_name(dtw->hscrollbar, "HorizontalScrollbar"); gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->hscrollbar, 1, 2, 1, 1); dtw->vscrollbar_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); #else @@ -492,6 +497,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) NULL, INKSCAPE_ICON("zoom-original"), _("Zoom drawing if window size changes")); + gtk_widget_set_name(dtw->sticky_zoom, "StickyZoom"); 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); @@ -501,6 +507,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) dtw->vscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(dtw->vadj)); + gtk_widget_set_name(dtw->vscrollbar, "VerticalScrollbar"); #else dtw->vscrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (dtw->vadj)); #endif @@ -528,6 +535,8 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) NULL, INKSCAPE_ICON("color-management"), tip ); + gtk_widget_set_name(dtw->cms_adjust, "CMS_Adjust"); + #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) { Glib::ustring current = prefs->getString("/options/displayprofile/uri"); @@ -564,7 +573,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) /* Canvas */ dtw->canvas = SP_CANVAS(SPCanvas::createAA()); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - dtw->canvas->enable_cms_display_adj = prefs->getBool("/options/displayprofile/enable"); + dtw->canvas->_enable_cms_display_adj = prefs->getBool("/options/displayprofile/enable"); #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) gtk_widget_set_can_focus (GTK_WIDGET (dtw->canvas), TRUE); @@ -572,10 +581,18 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) sp_ruler_add_track_widget (SP_RULER(dtw->vruler), GTK_WIDGET(dtw->canvas)); #if GTK_CHECK_VERSION(3,0,0) - GdkRGBA white = {1,1,1,1}; - gtk_widget_override_background_color(GTK_WIDGET(dtw->canvas), - GTK_STATE_FLAG_NORMAL, - &white); + GtkCssProvider *css_provider = gtk_css_provider_new(); + GtkStyleContext *style_context = gtk_widget_get_style_context(GTK_WIDGET(dtw->canvas)); + + gtk_css_provider_load_from_data(css_provider, + "SPCanvas {\n" + " background-color: white;\n" + "}\n", + -1, NULL); + + gtk_style_context_add_provider(style_context, + GTK_STYLE_PROVIDER(css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); #else GtkStyle *style = gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(dtw->canvas))); style->bg[GTK_STATE_NORMAL] = style->white; @@ -599,9 +616,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) if (create_dock) { dtw->dock = new Inkscape::UI::Widget::Dock(); - #if WITH_GTKMM_3_0 Gtk::Paned *paned = new Gtk::Paned(); + paned->set_name("Canvas_and_Dock"); #else Gtk::HPaned *paned = new Gtk::HPaned(); #endif @@ -618,9 +635,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) gtk_widget_set_hexpand(GTK_WIDGET(paned->gobj()), TRUE); gtk_widget_set_vexpand(GTK_WIDGET(paned->gobj()), TRUE); - gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1); + gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1); #else - gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); #endif @@ -628,17 +645,26 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #if GTK_CHECK_VERSION(3,0,0) gtk_widget_set_hexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE); gtk_widget_set_vexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE); - gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1); + gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1); #else - gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0); #endif } + // connect scrollbar signals + g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + + + // --------------- Status Tool Bar ------------------// + + // Selected Style (Fill/Stroke/Opacity) dtw->selected_style = new Inkscape::UI::Widget::SelectedStyle(true); GtkHBox *ss_ = dtw->selected_style->gobj(); gtk_box_pack_start (GTK_BOX (dtw->statusbar), GTK_WIDGET(ss_), FALSE, FALSE, 0); + // Separator gtk_box_pack_start(GTK_BOX(dtw->statusbar), #if GTK_CHECK_VERSION(3,0,0) gtk_separator_new(GTK_ORIENTATION_VERTICAL), @@ -647,15 +673,39 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #endif FALSE, FALSE, 0); - // connect scrollbar signals - g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); - g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw); + // Layer Selector + dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL); + // FIXME: need to unreference on container destruction to avoid leak + dtw->layer_selector->reference(); + //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON); + gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1); - GtkWidget *statusbar_tail=gtk_statusbar_new(); - gtk_box_pack_end (GTK_BOX (dtw->statusbar), statusbar_tail, FALSE, FALSE, 0); + // Select Status + dtw->select_status = gtk_label_new (NULL); + gtk_widget_set_name( dtw->select_status, "SelectStatus"); + gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END); +#if GTK_CHECK_VERSION(3,10,0) + gtk_label_set_line_wrap (GTK_LABEL(dtw->select_status), true); + gtk_label_set_lines (GTK_LABEL(dtw->select_status), 2); +#endif - // zoom status spinbutton +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(dtw->select_status, GTK_ALIGN_START); +#else + gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5); +#endif + + gtk_widget_set_size_request (dtw->select_status, 1, -1); + + // Display the initial welcome message in the statusbar + gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them.")); + + gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status, TRUE, TRUE, 0); + + + // Zoom status spinbutton dtw->zoom_status = gtk_spin_button_new_with_range (log(SP_DESKTOP_ZOOM_MIN)/log(2), log(SP_DESKTOP_ZOOM_MAX)/log(2), 0.1); + gtk_widget_set_name(dtw->zoom_status, "ZoomStatus"); gtk_widget_set_tooltip_text (dtw->zoom_status, _("Zoom")); gtk_widget_set_size_request (dtw->zoom_status, STATUS_ZOOM_WIDTH, -1); gtk_entry_set_width_chars (GTK_ENTRY (dtw->zoom_status), 6); @@ -669,12 +719,14 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "value_changed", G_CALLBACK (sp_dtw_zoom_value_changed), dtw); dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "populate_popup", G_CALLBACK (sp_dtw_zoom_populate_popup), dtw); - // cursor coordinates + // Cursor coordinates #if GTK_CHECK_VERSION(3,0,0) dtw->coord_status = gtk_grid_new(); + gtk_widget_set_name(dtw->coord_status, "CoordinateAndZStatus"); gtk_grid_set_row_spacing(GTK_GRID(dtw->coord_status), 0); gtk_grid_set_column_spacing(GTK_GRID(dtw->coord_status), 2); GtkWidget* sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + gtk_widget_set_name(sep, "CoordinateSeparator"); gtk_grid_attach(GTK_GRID(dtw->coord_status), GTK_WIDGET(sep), 0, 0, 1, 2); @@ -688,42 +740,40 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) GTK_FILL, GTK_FILL, 0, 0); #endif - eventbox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (eventbox), dtw->coord_status); - gtk_widget_set_tooltip_text (eventbox, _("Cursor coordinates")); + gtk_widget_set_tooltip_text (dtw->coord_status, _("Cursor coordinates")); GtkWidget *label_x = gtk_label_new(_("X:")); - gtk_misc_set_alignment (GTK_MISC(label_x), 0.0, 0.5); - -#if GTK_CHECK_VERSION(3,0,0) - gtk_grid_attach(GTK_GRID(dtw->coord_status), - label_x, 1, 0, 1, 1); -#else - gtk_table_attach(GTK_TABLE(dtw->coord_status), label_x, 1,2, 0,1, GTK_FILL, GTK_FILL, 0, 0); -#endif - GtkWidget *label_y = gtk_label_new(_("Y:")); - gtk_misc_set_alignment (GTK_MISC(label_y), 0.0, 0.5); #if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(label_x, GTK_ALIGN_START); + gtk_widget_set_halign(label_y, GTK_ALIGN_START); + gtk_grid_attach(GTK_GRID(dtw->coord_status), label_x, 1, 0, 1, 1); gtk_grid_attach(GTK_GRID(dtw->coord_status), label_y, 1, 1, 1, 1); #else + gtk_misc_set_alignment (GTK_MISC(label_x), 0.0, 0.5); + gtk_misc_set_alignment (GTK_MISC(label_y), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(dtw->coord_status), label_x, 1,2, 0,1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(dtw->coord_status), label_y, 1,2, 1,2, GTK_FILL, GTK_FILL, 0, 0); #endif dtw->coord_status_x = gtk_label_new(NULL); - gtk_label_set_markup( GTK_LABEL(dtw->coord_status_x), "<tt> 0.00 </tt>" ); - gtk_misc_set_alignment (GTK_MISC(dtw->coord_status_x), 1.0, 0.5); dtw->coord_status_y = gtk_label_new(NULL); + gtk_label_set_markup( GTK_LABEL(dtw->coord_status_x), "<tt> 0.00 </tt>" ); gtk_label_set_markup( GTK_LABEL(dtw->coord_status_y), "<tt> 0.00 </tt>" ); - gtk_misc_set_alignment (GTK_MISC(dtw->coord_status_y), 1.0, 0.5); + GtkWidget* label_z = gtk_label_new(_("Z:")); + gtk_widget_set_name(label_z, "ZLabel"); #if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(dtw->coord_status_x, GTK_ALIGN_END); + gtk_widget_set_halign(dtw->coord_status_y, GTK_ALIGN_END); gtk_grid_attach(GTK_GRID(dtw->coord_status), dtw->coord_status_x, 2, 0, 1, 1); gtk_grid_attach(GTK_GRID(dtw->coord_status), dtw->coord_status_y, 2, 1, 1, 1); gtk_grid_attach(GTK_GRID(dtw->coord_status), label_z, 3, 0, 1, 2); gtk_grid_attach(GTK_GRID(dtw->coord_status), dtw->zoom_status, 4, 0, 1, 2); #else + gtk_misc_set_alignment (GTK_MISC(dtw->coord_status_x), 1.0, 0.5); + 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), label_z, 3,4, 0,2, GTK_FILL, GTK_FILL, 0, 0); @@ -731,14 +781,10 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) #endif sp_set_font_size_smaller (dtw->coord_status); - gtk_box_pack_end (GTK_BOX (statusbar_tail), eventbox, FALSE, FALSE, 1); - dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL); - // FIXME: need to unreference on container destruction to avoid leak - dtw->layer_selector->reference(); - //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON); - gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1); + gtk_box_pack_end (GTK_BOX (dtw->statusbar), dtw->coord_status, FALSE, FALSE, 0); + // --------------- Color Management ---------------- // dtw->_tracker = ege_color_prof_tracker_new(GTK_WIDGET(dtw->layer_selector->gobj())); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display"); @@ -746,31 +792,14 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) Glib::ustring id = Inkscape::CMSSystem::getDisplayId( 0, 0 ); bool enabled = false; - dtw->canvas->cms_key = id; - enabled = !dtw->canvas->cms_key.empty(); + dtw->canvas->_cms_key = id; + enabled = !dtw->canvas->_cms_key.empty(); cms_adjust_set_sensitive( dtw, enabled ); } #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(sp_dtw_color_profile_event), dtw ); - dtw->select_status_eventbox = gtk_event_box_new (); - dtw->select_status = gtk_label_new (NULL); - gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END); - gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5); - gtk_widget_set_size_request (dtw->select_status, 1, -1); - // display the initial welcome message in the statusbar - gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them.")); - // space label 2 pixels from left edge - gtk_container_add (GTK_CONTAINER (dtw->select_status_eventbox), dtw->select_status); -#if GTK_CHECK_VERSION(3,0,0) - gtk_box_pack_start(GTK_BOX(dtw->statusbar), - gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), - FALSE, FALSE, 2); -#else - gtk_box_pack_start (GTK_BOX (dtw->statusbar), gtk_hbox_new(FALSE, 0), FALSE, FALSE, 2); -#endif - gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status_eventbox, TRUE, TRUE, 0); - + // ------------------ Finish Up -------------------- // gtk_widget_show_all (dtw->vbox); gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas)); @@ -1035,7 +1064,7 @@ sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dt // current item on the canvas, because item events and all mouse events are caught // and passed on by the canvas acetate (I think). --bb if ((event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) - && !dtw->canvas->current_item) { + && !dtw->canvas->_current_item) { return sp_desktop_root_handler (NULL, event, dtw->desktop); } } @@ -1054,9 +1083,9 @@ void sp_dtw_color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidge gint monitor = gdk_screen_get_monitor_at_window(screen, window); Glib::ustring id = Inkscape::CMSSystem::getDisplayId( screenNum, monitor ); bool enabled = false; - dtw->canvas->cms_key = id; + dtw->canvas->_cms_key = id; dtw->requestCanvasUpdate(); - enabled = !dtw->canvas->cms_key.empty(); + enabled = !dtw->canvas->_cms_key.empty(); cms_adjust_set_sensitive( dtw, enabled ); } #else @@ -1092,8 +1121,8 @@ void cms_adjust_toggled( GtkWidget */*button*/, gpointer data ) 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; + if ( down != dtw->canvas->_enable_cms_display_adj ) { + dtw->canvas->_enable_cms_display_adj = down; dtw->requestCanvasUpdate(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/options/displayprofile/enable", down); @@ -1439,6 +1468,7 @@ bool SPDesktopWidget::showInfoDialog( Glib::ustring const &message ) GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", message.c_str()); + gtk_widget_set_name(dialog, "InfoDialog"); gtk_window_set_title( GTK_WINDOW(dialog), _("Note:")); // probably want to take this as a parameter. gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); @@ -1685,7 +1715,11 @@ void SPDesktopWidget::setToolboxPosition(Glib::ustring const& id, GtkPositionTyp case GTK_POS_TOP: case GTK_POS_BOTTOM: if ( gtk_widget_is_ancestor(toolbox, hbox) ) { - gtk_widget_reparent( toolbox, vbox ); + // Removing a widget can reduce ref count to zero + g_object_ref(G_OBJECT(toolbox)); + gtk_container_remove(GTK_CONTAINER(hbox), toolbox); + gtk_container_add(GTK_CONTAINER(vbox), toolbox); + g_object_unref(G_OBJECT(toolbox)); gtk_box_set_child_packing(GTK_BOX(vbox), toolbox, FALSE, TRUE, 0, GTK_PACK_START); } ToolboxFactory::setOrientation(toolbox, GTK_ORIENTATION_HORIZONTAL); @@ -1693,7 +1727,10 @@ void SPDesktopWidget::setToolboxPosition(Glib::ustring const& id, GtkPositionTyp case GTK_POS_LEFT: case GTK_POS_RIGHT: if ( !gtk_widget_is_ancestor(toolbox, hbox) ) { - gtk_widget_reparent( toolbox, hbox ); + g_object_ref(G_OBJECT(toolbox)); + gtk_container_remove(GTK_CONTAINER(vbox), toolbox); + gtk_container_add(GTK_CONTAINER(hbox), toolbox); + g_object_unref(G_OBJECT(toolbox)); 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 ); @@ -1744,6 +1781,7 @@ SPDesktopWidget* SPDesktopWidget::createInstance(SPNamedView *namedview) dtw->layer_selector->setDesktop(dtw->desktop); dtw->menubar = sp_ui_main_menubar (dtw->desktop); + gtk_widget_set_name(dtw->menubar, "MenuBar"); gtk_widget_show_all (dtw->menubar); gtk_box_pack_start (GTK_BOX (dtw->vbox), dtw->menubar, FALSE, FALSE, 0); diff --git a/src/widgets/eek-preview.cpp b/src/widgets/eek-preview.cpp index 19dbb04ab..9951a8957 100644 --- a/src/widgets/eek-preview.cpp +++ b/src/widgets/eek-preview.cpp @@ -239,7 +239,7 @@ static gboolean eek_preview_draw(GtkWidget *widget, cairo_t *cr) { - GtkStyle *style = gtk_widget_get_style(widget); + EekPreview *preview = EEK_PREVIEW(widget); EekPreviewPrivate *priv = EEK_PREVIEW_GET_PRIVATE(preview); @@ -284,7 +284,8 @@ gboolean eek_preview_draw(GtkWidget *widget, 0, 0, allocation.width, allocation.height); #else - GdkWindow* window = gtk_widget_get_window(widget); + GtkStyle *style = gtk_widget_get_style(widget); + GdkWindow *window = gtk_widget_get_window(widget); gtk_paint_flat_box( style, window, @@ -495,14 +496,11 @@ gboolean eek_preview_draw(GtkWidget *widget, otherArea.y = possible.y + (possible.height - otherArea.height) / 2; } #if GTK_CHECK_VERSION(3,0,0) - gtk_paint_diamond( style, - cr, - gtk_widget_get_state (widget), - GTK_SHADOW_ETCHED_OUT, - widget, - NULL, - otherArea.x, otherArea.y, - otherArea.width, otherArea.height ); + // This should be a diamond too? + gtk_render_check(context, + cr, + otherArea.x, otherArea.y, + otherArea.width, otherArea.height ); #else gtk_paint_diamond( style, window, @@ -549,7 +547,11 @@ static gboolean eek_preview_enter_cb( GtkWidget* widget, GdkEventCrossing* event EekPreviewPrivate *priv = EEK_PREVIEW_GET_PRIVATE(preview); priv->within = TRUE; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_state_flags( widget, priv->hot ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_PRELIGHT, false ); +#else gtk_widget_set_state( widget, priv->hot ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT ); +#endif } return FALSE; @@ -562,7 +564,11 @@ static gboolean eek_preview_leave_cb( GtkWidget* widget, GdkEventCrossing* event EekPreviewPrivate *priv = EEK_PREVIEW_GET_PRIVATE(preview); priv->within = FALSE; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_state_flags( widget, GTK_STATE_FLAG_NORMAL, false ); +#else gtk_widget_set_state( widget, GTK_STATE_NORMAL ); +#endif } return FALSE; @@ -587,7 +593,11 @@ static gboolean eek_preview_button_press_cb( GtkWidget* widget, GdkEventButton* if ( priv->within ) { +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_state_flags( widget, GTK_STATE_FLAG_ACTIVE, false ); +#else gtk_widget_set_state( widget, GTK_STATE_ACTIVE ); +#endif } } } @@ -602,7 +612,11 @@ static gboolean eek_preview_button_release_cb( GtkWidget* widget, GdkEventButton EekPreviewPrivate *priv = EEK_PREVIEW_GET_PRIVATE(preview); priv->hot = FALSE; +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_state_flags( widget, GTK_STATE_FLAG_NORMAL, false ); +#else gtk_widget_set_state( widget, GTK_STATE_NORMAL ); +#endif if ( priv->within && (event->button == PRIME_BUTTON_MAGIC_NUMBER || diff --git a/src/widgets/ege-adjustment-action.cpp b/src/widgets/ege-adjustment-action.cpp index a91149f4c..272217aa4 100644 --- a/src/widgets/ege-adjustment-action.cpp +++ b/src/widgets/ege-adjustment-action.cpp @@ -865,7 +865,13 @@ static GtkWidget* create_tool_item( GtkAction* action ) gtk_box_pack_start( GTK_BOX(hb), icon, FALSE, FALSE, 0 ); } else { GtkWidget* lbl = gtk_label_new( g_value_get_string( &value ) ? g_value_get_string( &value ) : "wwww" ); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(lbl, GTK_ALIGN_END); +#else gtk_misc_set_alignment( GTK_MISC(lbl), 1.0, 0.5 ); +#endif + gtk_box_pack_start( GTK_BOX(hb), lbl, FALSE, FALSE, 0 ); } } diff --git a/src/widgets/ege-select-one-action.cpp b/src/widgets/ege-select-one-action.cpp index ab86c49f8..2e106154e 100644 --- a/src/widgets/ege-select-one-action.cpp +++ b/src/widgets/ege-select-one-action.cpp @@ -818,9 +818,14 @@ GtkWidget* create_tool_item( GtkAction* action ) gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 ); { +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(holder, GTK_ALIGN_START); + gtk_container_add(GTK_CONTAINER(item), holder); +#else GtkWidget *align = gtk_alignment_new(0, 0.5, 0, 0); gtk_container_add( GTK_CONTAINER(align), holder); gtk_container_add( GTK_CONTAINER(item), align ); +#endif } } @@ -855,10 +860,14 @@ void resync_active( EgeSelectOneAction* act, gint active, gboolean override ) GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); if ( children && children->data ) { gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); + +#if !GTK_CHECK_VERSION(3,0,0) if (!combodata && GTK_IS_ALIGNMENT(children->data)) { GList *other = gtk_container_get_children( GTK_CONTAINER(children->data) ); combodata = g_object_get_data( G_OBJECT(other->data), "ege-combo-box" ); } +#endif + if ( GTK_IS_COMBO_BOX(combodata) ) { GtkComboBox* combo = GTK_COMBO_BOX(combodata); if ((active == -1) && (gtk_combo_box_get_has_entry(combo))) { @@ -915,10 +924,14 @@ void resync_sensitive( EgeSelectOneAction* act ) GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); if ( children && children->data ) { gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); + +#if !GTK_CHECK_VERSION(3,0,0) if (!combodata && GTK_IS_ALIGNMENT(children->data)) { GList *other = gtk_container_get_children( GTK_CONTAINER(children->data) ); combodata = g_object_get_data( G_OBJECT(other->data), "ege-combo-box" ); } +#endif + if ( GTK_IS_COMBO_BOX(combodata) ) { /* Not implemented */ } else if ( GTK_IS_BOX(children->data) ) { diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp index 1f79b50f2..bb553f4e6 100644 --- a/src/widgets/eraser-toolbar.cpp +++ b/src/widgets/eraser-toolbar.cpp @@ -57,6 +57,13 @@ static void sp_erc_width_value_changed( GtkAdjustment *adj, GObject *tbl ) update_presets_list(tbl); } +static void sp_erc_mass_value_changed( GtkAdjustment *adj, GObject* tbl ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setDouble( "/tools/eraser/mass", gtk_adjustment_get_value(adj) ); + update_presets_list(tbl); +} + static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl ) { SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); @@ -65,7 +72,18 @@ static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl ) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool( "/tools/eraser/mode", eraserMode ); } - + GtkAction *split = GTK_ACTION( g_object_get_data(tbl, "split") ); + GtkAction *mass = GTK_ACTION( g_object_get_data(tbl, "mass") ); + GtkAction *width = GTK_ACTION( g_object_get_data(tbl, "width") ); + if(eraserMode == TRUE){ + gtk_action_set_visible( split, TRUE ); + gtk_action_set_visible( mass, TRUE ); + gtk_action_set_visible( width, TRUE ); + } else { + gtk_action_set_visible( split, FALSE ); + gtk_action_set_visible( mass, FALSE ); + gtk_action_set_visible( width, FALSE ); + } // only take action if run by the attr_changed listener if (!g_object_get_data( tbl, "freeze" )) { // in turn, prevent listener from responding @@ -82,11 +100,20 @@ static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl ) } } +static void sp_toogle_break_apart( GtkToggleAction* act, gpointer data ) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean active = gtk_toggle_action_get_active(act); + prefs->setBool("/tools/eraser/break_apart", active); +} + void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { + Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gint eraserMode = FALSE; { GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); - GtkTreeIter iter; gtk_list_store_append( model, &iter ); gtk_list_store_set( model, &iter, @@ -113,29 +140,70 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb ege_select_one_action_set_icon_column( act, 2 ); ege_select_one_action_set_tooltip_column( act, 1 ); - /// @todo Convert to boolean? Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0; + eraserMode = prefs->getBool("/tools/eraser/mode") ? TRUE : FALSE; ege_select_one_action_set_active( act, eraserMode ); g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_erasertb_mode_changed), holder ); } { /* Width */ - gchar const* labels[] = {_("(hairline)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad stroke)")}; - gdouble values[] = {1, 3, 5, 10, 15, 20, 30, 50, 75, 100}; + gchar const* labels[] = {_("(no width)"),_("(hairline)"), 0, 0, 0, _("(default)"), 0, 0, 0, 0, _("(broad stroke)")}; + gdouble values[] = {0, 1, 3, 5, 10, 15, 20, 30, 50, 75, 100}; EgeAdjustmentAction *eact = create_adjustment_action( "EraserWidthAction", _("Pen Width"), _("Width:"), _("The width of the eraser pen (relative to the visible canvas area)"), "/tools/eraser/width", 15, GTK_WIDGET(desktop->canvas), holder, TRUE, "altx-eraser", - 1, 100, 1.0, 10.0, + 0, 100, 1.0, 10.0, labels, values, G_N_ELEMENTS(labels), sp_erc_width_value_changed, NULL /*unit tracker*/, 1, 0); ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + g_object_set_data( holder, "width", eact ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } + { + /* Mass */ + gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")}; + gdouble values[] = {0.0, 2, 10, 20, 50, 100}; + EgeAdjustmentAction* eact = create_adjustment_action( "EraserMassAction", + _("Eraser Mass"), _("Mass:"), + _("Increase to make the eraser drag behind, as if slowed by inertia"), + "/tools/eraser/mass", 10.0, + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, + 0.0, 100, 1, 10.0, + labels, values, G_N_ELEMENTS(labels), + sp_erc_mass_value_changed, NULL /*unit tracker*/, 1, 0); + ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); + g_object_set_data( holder, "mass", eact ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); + } + /* Overlap */ + { + InkToggleAction* act = ink_toggle_action_new( "EraserBreakAppart", + _("Break apart cut items"), + _("Break apart cut items"), + INKSCAPE_ICON("distribute-randomize"), + secondarySize ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/eraser/break_apart", false) ); + g_object_set_data( holder, "split", act ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_toogle_break_apart), holder) ; + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } + GtkAction *split = GTK_ACTION( g_object_get_data(holder, "split") ); + GtkAction *mass = GTK_ACTION( g_object_get_data(holder, "mass") ); + GtkAction *width = GTK_ACTION( g_object_get_data(holder, "width") ); + if(eraserMode == TRUE){ + gtk_action_set_visible( split, TRUE ); + gtk_action_set_visible( mass, TRUE ); + gtk_action_set_visible( width, TRUE ); + } else { + gtk_action_set_visible( split, FALSE ); + gtk_action_set_visible( mass, FALSE ); + gtk_action_set_visible( width, FALSE ); + } } diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp index 943434868..aefcb2e81 100644 --- a/src/widgets/font-selector.cpp +++ b/src/widgets/font-selector.cpp @@ -159,9 +159,24 @@ static void sp_font_selector_init(SPFontSelector *fsel) /* Muck with style, see text-toolbar.cpp */ gtk_widget_set_name( GTK_WIDGET(fsel->family_treeview), "font_selector_family" ); + +#if GTK_CHECK_VERSION(3,0,0) + GtkCssProvider *css_provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(css_provider, + "#font_selector_family {\n" + " -GtkWidget-wide-separators: true;\n" + " -GtkWidget-separator-height: 6;\n" + "}\n", + -1, NULL); + + GdkScreen *screen = gdk_screen_get_default(); + gtk_style_context_add_provider_for_screen(screen, + GTK_STYLE_PROVIDER(css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); +#else gtk_rc_parse_string ( "widget \"*font_selector_family\" style \"fontfamily-separator-style\""); - +#endif Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); Glib::RefPtr<Gtk::ListStore> store = fontlister->get_font_list(); diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 35c1e4a8d..3aa44c90a 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -914,7 +914,13 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s /* Label */ GtkWidget *l = gtk_label_new(C_("Gradient","Offset:")); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(l, GTK_ALIGN_END); +#else gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); +#endif + gtk_box_pack_start(GTK_BOX(hb),l, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS); gtk_widget_show(l); diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 542d16797..f2031fe51 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -232,6 +232,7 @@ void IconImpl::sizeAllocate(GtkWidget *widget, GtkAllocation *allocation) } } +// GTK3 Only, Doesn't actually seem to be used. gboolean IconImpl::draw(GtkWidget *widget, cairo_t* cr) { SPIcon *icon = SP_ICON(widget); @@ -247,24 +248,34 @@ gboolean IconImpl::draw(GtkWidget *widget, cairo_t* cr) if (gtk_widget_get_state_flags (GTK_WIDGET(icon)) != GTK_STATE_FLAG_NORMAL && image) { #else if (gtk_widget_get_state (GTK_WIDGET(icon)) != GTK_STATE_NORMAL && image) { + std::cerr << "IconImpl::draw: Ooops! It is called in GTK2" << std::endl; #endif + std::cerr << "IconImpl::draw: No image, creating fallback" << std::endl; + +#if GTK_CHECK_VERSION(3,0,0) + // image = gtk_render_icon_pixbuf(gtk_widget_get_style_context(widget), + // source, + // (GtkIconSize)-1); + + // gtk_render_icon_pixbuf deprecated, replaced by: + GtkIconTheme *icon_theme = gtk_icon_theme_get_default(); + image = gtk_icon_theme_load_icon (icon_theme, + "gtk-image", + 32, + (GtkIconLookupFlags)0, + NULL); +#else GtkIconSource *source = gtk_icon_source_new(); gtk_icon_source_set_pixbuf(source, icon->pb); gtk_icon_source_set_size(source, GTK_ICON_SIZE_SMALL_TOOLBAR); // note: this is boilerplate and not used gtk_icon_source_set_size_wildcarded(source, FALSE); - -#if GTK_CHECK_VERSION(3,0,0) - image = gtk_render_icon_pixbuf(gtk_widget_get_style_context(widget), - source, - (GtkIconSize)-1); -#else image = gtk_style_render_icon(gtk_widget_get_style(widget), source, gtk_widget_get_direction(widget), (GtkStateType) gtk_widget_get_state(widget), (GtkIconSize)-1, widget, "gtk-image"); + gtk_icon_source_free(source); #endif - gtk_icon_source_free(source); unref_image = true; } @@ -272,7 +283,13 @@ gboolean IconImpl::draw(GtkWidget *widget, cairo_t* cr) GtkAllocation allocation; GtkRequisition requisition; gtk_widget_get_allocation(widget, &allocation); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_get_preferred_size(widget, &requisition, NULL); +#else gtk_widget_get_requisition(widget, &requisition); +#endif + int x = floor(allocation.x + ((allocation.width - requisition.width) * 0.5)); int y = floor(allocation.y + ((allocation.height - requisition.height) * 0.5)); int width = gdk_pixbuf_get_width(image); @@ -787,6 +804,10 @@ GtkWidget *IconImpl::newFull( Inkscape::IconSize lsize, gchar const *name ) GtkWidget *widget = NULL; gint trySize = CLAMP( static_cast<gint>(lsize), 0, static_cast<gint>(G_N_ELEMENTS(iconSizeLookup) - 1) ); + if (trySize != lsize ) { + std::cerr << "GtkWidget *IconImple::newFull(): lsize != trySize: lsize: " << lsize + << " try Size: " << trySize << " " << (name?name:"NULL") << std::endl; + } if ( !sizeMapDone ) { injectCustomSize(); } @@ -814,6 +835,7 @@ GtkWidget *IconImpl::newFull( Inkscape::IconSize lsize, gchar const *name ) if ( Inkscape::Preferences::get()->getBool("/options/iconrender/named_nodelay") ) { int psize = getPhysSize(lsize); + // std::cout << " name: " << name << " size: " << psize << std::endl; prerenderIcon(name, mappedSize, psize); } else { addPreRender( mappedSize, name ); @@ -986,8 +1008,6 @@ int IconImpl::getPhysSize(int size) "inkscape-decoration" }; - GtkWidget *icon = GTK_WIDGET(g_object_new(SP_TYPE_ICON, NULL)); - for (unsigned i = 0; i < G_N_ELEMENTS(gtkSizes); ++i) { guint const val_ix = (gtkSizes[i] <= GTK_ICON_SIZE_DIALOG) ? (guint)gtkSizes[i] : (guint)Inkscape::ICON_SIZE_DECORATION; @@ -1012,7 +1032,12 @@ int IconImpl::getPhysSize(int size) // gtk_icon_size_lookup(), because themes are free to render the pixbuf however // they like, including changing the usual size." gchar const *id = INKSCAPE_ICON("document-open"); - GdkPixbuf *pb = gtk_widget_render_icon( icon, id, gtkSizes[i], NULL); + GtkIconTheme *icon_theme = gtk_icon_theme_get_default(); + GdkPixbuf *pb = gtk_icon_theme_load_icon (icon_theme, + id, + vals[val_ix], + (GtkIconLookupFlags)0, + NULL); if (pb) { width = gdk_pixbuf_get_width(pb); height = gdk_pixbuf_get_height(pb); @@ -1028,7 +1053,6 @@ int IconImpl::getPhysSize(int size) g_object_unref(G_OBJECT(pb)); } } - //g_object_unref(icon); init = true; } diff --git a/src/widgets/image-menu-item.c b/src/widgets/image-menu-item.c new file mode 100644 index 000000000..2b9500ba0 --- /dev/null +++ b/src/widgets/image-menu-item.c @@ -0,0 +1,1071 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2001 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. + * Forked by . Icons in menus are important to us. + */ + +#include "config.h" + +#include <glib/gi18n-lib.h> +#include <gtk/gtk.h> + +#include "widgets/image-menu-item.h" + +/** + * SECTION:gtkimagemenuitem + * @Short_description: A menu item with an icon + * @Title: ImageMenuItem + * + * A ImageMenuItem is a menu item which has an icon next to the text label. + * + * Note that the user can disable display of menu icons, so make sure to still + * fill in the text label. + */ + + +struct _ImageMenuItemPrivate +{ + GtkWidget *image; + + gchar *label; + guint use_stock : 1; + guint toggle_size; +}; + +enum { + PROP_0, + PROP_IMAGE, + PROP_USE_STOCK, + PROP_ACCEL_GROUP, +}; + +static GtkActivatableIface *parent_activatable_iface; + +static void image_menu_item_destroy (GtkWidget *widget); +static void image_menu_item_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void image_menu_item_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); +static void image_menu_item_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum, + gint *natural); +static void image_menu_item_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void image_menu_item_map (GtkWidget *widget); +static void image_menu_item_remove (GtkContainer *container, + GtkWidget *child); +static void image_menu_item_toggle_size_request (GtkMenuItem *menu_item, + gint *requisition); +static void image_menu_item_set_label (GtkMenuItem *menu_item, + const gchar *label); +static const gchar * image_menu_item_get_label (GtkMenuItem *menu_item); + +static void image_menu_item_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); + +static void image_menu_item_finalize (GObject *object); +static void image_menu_item_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void image_menu_item_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void image_menu_item_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen); + +static void image_menu_item_recalculate (ImageMenuItem *image_menu_item); + +static void image_menu_item_activatable_interface_init (GtkActivatableIface *iface); +static void image_menu_item_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name); +static void image_menu_item_sync_action_properties (GtkActivatable *activatable, + GtkAction *action); + + +G_DEFINE_TYPE_WITH_CODE (ImageMenuItem, image_menu_item, GTK_TYPE_MENU_ITEM, + G_ADD_PRIVATE (ImageMenuItem) + G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, + image_menu_item_activatable_interface_init)) + + +static void +image_menu_item_class_init (ImageMenuItemClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; + GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass; + GtkContainerClass *container_class = (GtkContainerClass*) klass; + + widget_class->destroy = image_menu_item_destroy; + widget_class->screen_changed = image_menu_item_screen_changed; + widget_class->get_preferred_width = image_menu_item_get_preferred_width; + widget_class->get_preferred_height = image_menu_item_get_preferred_height; + widget_class->get_preferred_height_for_width = image_menu_item_get_preferred_height_for_width; + widget_class->size_allocate = image_menu_item_size_allocate; + widget_class->map = image_menu_item_map; + + container_class->forall = image_menu_item_forall; + container_class->remove = image_menu_item_remove; + + menu_item_class->toggle_size_request = image_menu_item_toggle_size_request; + menu_item_class->set_label = image_menu_item_set_label; + menu_item_class->get_label = image_menu_item_get_label; + + gobject_class->finalize = image_menu_item_finalize; + gobject_class->set_property = image_menu_item_set_property; + gobject_class->get_property = image_menu_item_get_property; + + /** + * ImageMenuItem:image: + * + * Child widget to appear next to the menu text. + * + */ + g_object_class_install_property (gobject_class, + PROP_IMAGE, + g_param_spec_object ("image", + _("Image widget"), + _("Child widget to appear next to the menu text"), + GTK_TYPE_WIDGET, + GTK_PARAM_READWRITE | G_PARAM_DEPRECATED)); + /** + * ImageMenuItem:use-stock: + * + * If %TRUE, the label set in the menuitem is used as a + * stock id to select the stock item for the item. + * + * Since: 2.16 + * + */ + g_object_class_install_property (gobject_class, + PROP_USE_STOCK, + g_param_spec_boolean ("use-stock", + _("Use stock"), + _("Whether to use the label text to create a stock menu item"), + FALSE, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_DEPRECATED)); + + /** + * ImageMenuItem:accel-group: + * + * The Accel Group to use for stock accelerator keys + * + * Since: 2.16 + * + */ + g_object_class_install_property (gobject_class, + PROP_ACCEL_GROUP, + g_param_spec_object ("accel-group", + _("Accel Group"), + _("The Accel Group to use for stock accelerator keys"), + GTK_TYPE_ACCEL_GROUP, + GTK_PARAM_WRITABLE | G_PARAM_DEPRECATED)); + +} + +static void +image_menu_item_init (ImageMenuItem *image_menu_item) +{ + ImageMenuItemPrivate *priv; + + image_menu_item->priv = image_menu_item_get_instance_private (image_menu_item); + priv = image_menu_item->priv; + + priv->image = NULL; + priv->use_stock = FALSE; + priv->label = NULL; +} + +static void +image_menu_item_finalize (GObject *object) +{ + ImageMenuItemPrivate *priv = IMAGE_MENU_ITEM (object)->priv; + + g_free (priv->label); + priv->label = NULL; + + G_OBJECT_CLASS (image_menu_item_parent_class)->finalize (object); +} + +static void +image_menu_item_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (object); + + switch (prop_id) + { + case PROP_IMAGE: + image_menu_item_set_image (image_menu_item, (GtkWidget *) g_value_get_object (value)); + break; + case PROP_USE_STOCK: + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + image_menu_item_set_use_stock (image_menu_item, g_value_get_boolean (value)); + G_GNUC_END_IGNORE_DEPRECATIONS; + break; + case PROP_ACCEL_GROUP: + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + image_menu_item_set_accel_group (image_menu_item, g_value_get_object (value)); + G_GNUC_END_IGNORE_DEPRECATIONS; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +image_menu_item_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (object); + + switch (prop_id) + { + case PROP_IMAGE: + g_value_set_object (value, image_menu_item_get_image (image_menu_item)); + break; + case PROP_USE_STOCK: + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + g_value_set_boolean (value, image_menu_item_get_use_stock (image_menu_item)); + G_GNUC_END_IGNORE_DEPRECATIONS; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +image_menu_item_map (GtkWidget *widget) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + + GTK_WIDGET_CLASS (image_menu_item_parent_class)->map (widget); + + if (priv->image) + g_object_set (priv->image, "visible", TRUE, NULL); +} + +static void +image_menu_item_destroy (GtkWidget *widget) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + + if (priv->image) + gtk_container_remove (GTK_CONTAINER (image_menu_item), + priv->image); + + GTK_WIDGET_CLASS (image_menu_item_parent_class)->destroy (widget); +} + +static void +image_menu_item_toggle_size_request (GtkMenuItem *menu_item, + gint *requisition) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (menu_item); + ImageMenuItemPrivate *priv = image_menu_item->priv; + GtkPackDirection pack_dir; + GtkWidget *parent; + GtkWidget *widget = GTK_WIDGET (menu_item); + + parent = gtk_widget_get_parent (widget); + + if (GTK_IS_MENU_BAR (parent)) + pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); + else + pack_dir = GTK_PACK_DIRECTION_LTR; + + *requisition = 0; + + if (priv->image && gtk_widget_get_visible (priv->image)) + { + GtkRequisition image_requisition; + guint toggle_spacing; + + gtk_widget_get_preferred_size (priv->image, &image_requisition, NULL); + + gtk_widget_style_get (GTK_WIDGET (menu_item), + "toggle-spacing", &toggle_spacing, + NULL); + + if (pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) + { + if (image_requisition.width > 0) + *requisition = image_requisition.width + toggle_spacing; + } + else + { + if (image_requisition.height > 0) + *requisition = image_requisition.height + toggle_spacing; + } + } +} + +static void +image_menu_item_recalculate (ImageMenuItem *image_menu_item) +{ + ImageMenuItemPrivate *priv = image_menu_item->priv; + GtkStockItem stock_item; + GtkWidget *image; + const gchar *resolved_label = priv->label; + + if (priv->use_stock && priv->label) + { + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + + if (!priv->image) + { + image = gtk_image_new_from_stock (priv->label, GTK_ICON_SIZE_MENU); + image_menu_item_set_image (image_menu_item, image); + } + + if (gtk_stock_lookup (priv->label, &stock_item)) + resolved_label = stock_item.label; + + gtk_menu_item_set_use_underline (GTK_MENU_ITEM (image_menu_item), TRUE); + + G_GNUC_END_IGNORE_DEPRECATIONS; + } + + GTK_MENU_ITEM_CLASS + (image_menu_item_parent_class)->set_label (GTK_MENU_ITEM (image_menu_item), resolved_label); + +} + +static void +image_menu_item_set_label (GtkMenuItem *menu_item, + const gchar *label) +{ + ImageMenuItemPrivate *priv = IMAGE_MENU_ITEM (menu_item)->priv; + + if (priv->label != label) + { + g_free (priv->label); + priv->label = g_strdup (label); + + image_menu_item_recalculate (IMAGE_MENU_ITEM (menu_item)); + + g_object_notify (G_OBJECT (menu_item), "label"); + + } +} + +static const gchar * +image_menu_item_get_label (GtkMenuItem *menu_item) +{ + ImageMenuItemPrivate *priv = IMAGE_MENU_ITEM (menu_item)->priv; + + return priv->label; +} + +static void +image_menu_item_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + GtkPackDirection pack_dir; + GtkWidget *parent; + + parent = gtk_widget_get_parent (widget); + + if (GTK_IS_MENU_BAR (parent)) + pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); + else + pack_dir = GTK_PACK_DIRECTION_LTR; + + GTK_WIDGET_CLASS (image_menu_item_parent_class)->get_preferred_width (widget, minimum, natural); + + if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) && + priv->image && + gtk_widget_get_visible (priv->image)) + { + gint child_minimum, child_natural; + + gtk_widget_get_preferred_width (priv->image, &child_minimum, &child_natural); + + *minimum = MAX (*minimum, child_minimum); + *natural = MAX (*natural, child_natural); + } +} + +static void +image_menu_item_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + gint child_height = 0; + GtkPackDirection pack_dir; + GtkWidget *parent; + + parent = gtk_widget_get_parent (widget); + + if (GTK_IS_MENU_BAR (parent)) + pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); + else + pack_dir = GTK_PACK_DIRECTION_LTR; + + if (priv->image && gtk_widget_get_visible (priv->image)) + { + GtkRequisition child_requisition; + + gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL); + + child_height = child_requisition.height; + } + + GTK_WIDGET_CLASS (image_menu_item_parent_class)->get_preferred_height (widget, minimum, natural); + + if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR) + { + *minimum = MAX (*minimum, child_height); + *natural = MAX (*natural, child_height); + } +} + +static void +image_menu_item_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum, + gint *natural) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + gint child_height = 0; + GtkPackDirection pack_dir; + GtkWidget *parent; + + parent = gtk_widget_get_parent (widget); + + if (GTK_IS_MENU_BAR (parent)) + pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); + else + pack_dir = GTK_PACK_DIRECTION_LTR; + + if (priv->image && gtk_widget_get_visible (priv->image)) + { + GtkRequisition child_requisition; + + gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL); + + child_height = child_requisition.height; + } + + GTK_WIDGET_CLASS + (image_menu_item_parent_class)->get_preferred_height_for_width (widget, width, minimum, natural); + + if (pack_dir == GTK_PACK_DIRECTION_RTL || pack_dir == GTK_PACK_DIRECTION_LTR) + { + *minimum = MAX (*minimum, child_height); + *natural = MAX (*natural, child_height); + } +} + + +static void +image_menu_item_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (widget); + ImageMenuItemPrivate *priv = image_menu_item->priv; + GtkAllocation widget_allocation; + GtkPackDirection pack_dir; + GtkWidget *parent; + + parent = gtk_widget_get_parent (widget); + + if (GTK_IS_MENU_BAR (parent)) + pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); + else + pack_dir = GTK_PACK_DIRECTION_LTR; + + GTK_WIDGET_CLASS (image_menu_item_parent_class)->size_allocate (widget, allocation); + + if (priv->image && gtk_widget_get_visible (priv->image)) + { + gint x, y, offset; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + GtkRequisition child_requisition; + GtkAllocation child_allocation; + guint horizontal_padding, toggle_spacing; + gint toggle_size; + + toggle_size = image_menu_item->priv->toggle_size; + gtk_widget_style_get (widget, + "horizontal-padding", &horizontal_padding, + "toggle-spacing", &toggle_spacing, + NULL); + + /* Man this is lame hardcoding action, but I can't + * come up with a solution that's really better. + */ + + gtk_widget_get_preferred_size (priv->image, &child_requisition, NULL); + + gtk_widget_get_allocation (widget, &widget_allocation); + + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + offset = gtk_container_get_border_width (GTK_CONTAINER (image_menu_item)); + + if (pack_dir == GTK_PACK_DIRECTION_LTR || + pack_dir == GTK_PACK_DIRECTION_RTL) + { + if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) == + (pack_dir == GTK_PACK_DIRECTION_LTR)) + x = offset + horizontal_padding + padding.left + + (toggle_size - toggle_spacing - child_requisition.width) / 2; + else + x = widget_allocation.width - offset - horizontal_padding - padding.right - + toggle_size + toggle_spacing + + (toggle_size - toggle_spacing - child_requisition.width) / 2; + + y = (widget_allocation.height - child_requisition.height) / 2; + } + else + { + if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) == + (pack_dir == GTK_PACK_DIRECTION_TTB)) + y = offset + horizontal_padding + padding.top + + (toggle_size - toggle_spacing - child_requisition.height) / 2; + else + y = widget_allocation.height - offset - horizontal_padding - padding.bottom - + toggle_size + toggle_spacing + + (toggle_size - toggle_spacing - child_requisition.height) / 2; + + x = (widget_allocation.width - child_requisition.width) / 2; + } + + child_allocation.width = child_requisition.width; + child_allocation.height = child_requisition.height; + child_allocation.x = widget_allocation.x + MAX (x, 0); + child_allocation.y = widget_allocation.y + MAX (y, 0); + + gtk_widget_size_allocate (priv->image, &child_allocation); + } +} + +static void +image_menu_item_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (container); + ImageMenuItemPrivate *priv = image_menu_item->priv; + + GTK_CONTAINER_CLASS (image_menu_item_parent_class)->forall (container, + include_internals, + callback, + callback_data); + + if (include_internals && priv->image) + (* callback) (priv->image, callback_data); +} + + +static void +image_menu_item_activatable_interface_init (GtkActivatableIface *iface) +{ + parent_activatable_iface = g_type_interface_peek_parent (iface); + iface->update = image_menu_item_update; + iface->sync_action_properties = image_menu_item_sync_action_properties; +} + +static gboolean +activatable_update_stock_id (ImageMenuItem *image_menu_item, GtkAction *action) +{ + GtkWidget *image; + const gchar *stock_id = gtk_action_get_stock_id (action); + + image = image_menu_item_get_image (image_menu_item); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + + if (GTK_IS_IMAGE (image) && + stock_id && gtk_icon_factory_lookup_default (stock_id)) + { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU); + G_GNUC_END_IGNORE_DEPRECATIONS; + return TRUE; + } + + G_GNUC_END_IGNORE_DEPRECATIONS; + + return FALSE; +} + +static gboolean +activatable_update_gicon (ImageMenuItem *image_menu_item, GtkAction *action) +{ + GtkWidget *image; + GIcon *icon = gtk_action_get_gicon (action); + const gchar *stock_id; + gboolean ret = FALSE; + + stock_id = gtk_action_get_stock_id (action); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + + image = image_menu_item_get_image (image_menu_item); + + if (icon && GTK_IS_IMAGE (image) && + !(stock_id && gtk_icon_factory_lookup_default (stock_id))) + { + gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU); + ret = TRUE; + } + + G_GNUC_END_IGNORE_DEPRECATIONS; + + return ret; +} + +static void +activatable_update_icon_name (ImageMenuItem *image_menu_item, GtkAction *action) +{ + GtkWidget *image; + const gchar *icon_name = gtk_action_get_icon_name (action); + + image = image_menu_item_get_image (image_menu_item); + + if (GTK_IS_IMAGE (image) && + (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY || + gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME)) + { + gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU); + } +} + +static void +image_menu_item_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name) +{ + ImageMenuItem *image_menu_item; + gboolean use_appearance; + + image_menu_item = IMAGE_MENU_ITEM (activatable); + + parent_activatable_iface->update (activatable, action, property_name); + + use_appearance = gtk_activatable_get_use_action_appearance (activatable); + if (!use_appearance) + return; + + if (strcmp (property_name, "stock-id") == 0) + activatable_update_stock_id (image_menu_item, action); + else if (strcmp (property_name, "gicon") == 0) + activatable_update_gicon (image_menu_item, action); + else if (strcmp (property_name, "icon-name") == 0) + activatable_update_icon_name (image_menu_item, action); +} + +static void +image_menu_item_sync_action_properties (GtkActivatable *activatable, + GtkAction *action) +{ + ImageMenuItem *image_menu_item; + GtkWidget *image; + gboolean use_appearance; + + image_menu_item = IMAGE_MENU_ITEM (activatable); + + parent_activatable_iface->sync_action_properties (activatable, action); + + if (!action) + return; + + use_appearance = gtk_activatable_get_use_action_appearance (activatable); + if (!use_appearance) + return; + + image = image_menu_item_get_image (image_menu_item); + if (image && !GTK_IS_IMAGE (image)) + { + image_menu_item_set_image (image_menu_item, NULL); + image = NULL; + } + + if (!image) + { + image = gtk_image_new (); + gtk_widget_show (image); + image_menu_item_set_image (IMAGE_MENU_ITEM (activatable), + image); + } + + if (!activatable_update_stock_id (image_menu_item, action) && + !activatable_update_gicon (image_menu_item, action)) + activatable_update_icon_name (image_menu_item, action); + +} + + +/** + * image_menu_item_new: + * + * Creates a new #ImageMenuItem with an empty label. + * + * Returns: a new #ImageMenuItem + * + */ +GtkWidget* +image_menu_item_new (void) +{ + return g_object_new (TYPE_IMAGE_MENU_ITEM, NULL); +} + +/** + * image_menu_item_new_with_label: + * @label: the text of the menu item. + * + * Creates a new #ImageMenuItem containing a label. + * + * Returns: a new #ImageMenuItem. + * + */ +GtkWidget* +image_menu_item_new_with_label (const gchar *label) +{ + return g_object_new (TYPE_IMAGE_MENU_ITEM, + "label", label, + NULL); +} + +/** + * image_menu_item_new_with_mnemonic: + * @label: the text of the menu item, with an underscore in front of the + * mnemonic character + * + * Creates a new #ImageMenuItem containing a label. The label + * will be created using gtk_label_new_with_mnemonic(), so underscores + * in @label indicate the mnemonic for the menu item. + * + * Returns: a new #ImageMenuItem + * + */ +GtkWidget* +image_menu_item_new_with_mnemonic (const gchar *label) +{ + return g_object_new (TYPE_IMAGE_MENU_ITEM, + "use-underline", TRUE, + "label", label, + NULL); +} + +/** + * image_menu_item_new_from_stock: + * @stock_id: the name of the stock item. + * @accel_group: (allow-none): the #GtkAccelGroup to add the menu items + * accelerator to, or %NULL. + * + * Creates a new #ImageMenuItem containing the image and text from a + * stock item. Some stock ids have preprocessor macros like #STOCK_OK + * and #STOCK_APPLY. + * + * If you want this menu item to have changeable accelerators, then pass in + * %NULL for accel_group. Next call gtk_menu_item_set_accel_path() with an + * appropriate path for the menu item, use gtk_stock_lookup() to look up the + * standard accelerator for the stock item, and if one is found, call + * gtk_accel_map_add_entry() to register it. + * + * Returns: a new #ImageMenuItem. + * + */ +GtkWidget* +image_menu_item_new_from_stock (const gchar *stock_id, + GtkAccelGroup *accel_group) +{ + return g_object_new (TYPE_IMAGE_MENU_ITEM, + "label", stock_id, + "use-stock", TRUE, + "accel-group", accel_group, + NULL); +} + +/** + * image_menu_item_set_use_stock: + * @image_menu_item: a #ImageMenuItem + * @use_stock: %TRUE if the menuitem should use a stock item + * + * If %TRUE, the label set in the menuitem is used as a + * stock id to select the stock item for the item. + * + * Since: 2.16 + * + */ +void +image_menu_item_set_use_stock (ImageMenuItem *image_menu_item, + gboolean use_stock) +{ + ImageMenuItemPrivate *priv; + + g_return_if_fail (IS_IMAGE_MENU_ITEM (image_menu_item)); + + priv = image_menu_item->priv; + + if (priv->use_stock != use_stock) + { + priv->use_stock = use_stock; + + image_menu_item_recalculate (image_menu_item); + + g_object_notify (G_OBJECT (image_menu_item), "use-stock"); + } +} + +/** + * image_menu_item_get_use_stock: + * @image_menu_item: a #ImageMenuItem + * + * Checks whether the label set in the menuitem is used as a + * stock id to select the stock item for the item. + * + * Returns: %TRUE if the label set in the menuitem is used as a + * stock id to select the stock item for the item + * + * Since: 2.16 + * + */ +gboolean +image_menu_item_get_use_stock (ImageMenuItem *image_menu_item) +{ + g_return_val_if_fail (IS_IMAGE_MENU_ITEM (image_menu_item), FALSE); + + return image_menu_item->priv->use_stock; +} + +/** + * image_menu_item_set_accel_group: + * @image_menu_item: a #ImageMenuItem + * @accel_group: the #GtkAccelGroup + * + * Specifies an @accel_group to add the menu items accelerator to + * (this only applies to stock items so a stock item must already + * be set, make sure to call image_menu_item_set_use_stock() + * and gtk_menu_item_set_label() with a valid stock item first). + * + * If you want this menu item to have changeable accelerators then + * you shouldnt need this (see image_menu_item_new_from_stock()). + * + * Since: 2.16 + * + */ +void +image_menu_item_set_accel_group (ImageMenuItem *image_menu_item, + GtkAccelGroup *accel_group) +{ + ImageMenuItemPrivate *priv; + GtkStockItem stock_item; + + /* Silent return for the constructor */ + if (!accel_group) + return; + + g_return_if_fail (IS_IMAGE_MENU_ITEM (image_menu_item)); + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); + + priv = image_menu_item->priv; + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + + if (priv->use_stock && priv->label && gtk_stock_lookup (priv->label, &stock_item)) + if (stock_item.keyval) + { + gtk_widget_add_accelerator (GTK_WIDGET (image_menu_item), + "activate", + accel_group, + stock_item.keyval, + stock_item.modifier, + GTK_ACCEL_VISIBLE); + + g_object_notify (G_OBJECT (image_menu_item), "accel-group"); + } + + G_GNUC_END_IGNORE_DEPRECATIONS; + +} + +/** + * image_menu_item_set_image: + * @image_menu_item: a #ImageMenuItem. + * @image: (allow-none): a widget to set as the image for the menu item. + * + * Sets the image of @image_menu_item to the given widget. + * Note that it depends on the show-menu-images setting whether + * the image will be displayed or not. + * + */ +void +image_menu_item_set_image (ImageMenuItem *image_menu_item, + GtkWidget *image) +{ + ImageMenuItemPrivate *priv; + + g_return_if_fail (IS_IMAGE_MENU_ITEM (image_menu_item)); + + priv = image_menu_item->priv; + + if (image == priv->image) + return; + + if (priv->image) + gtk_container_remove (GTK_CONTAINER (image_menu_item), + priv->image); + + priv->image = image; + + if (image == NULL) + return; + + gtk_widget_set_parent (image, GTK_WIDGET (image_menu_item)); + g_object_set (image, "visible", TRUE, "no-show-all", TRUE, NULL); + + g_object_notify (G_OBJECT (image_menu_item), "image"); +} + +/** + * image_menu_item_get_image: + * @image_menu_item: a #ImageMenuItem + * + * Gets the widget that is currently set as the image of @image_menu_item. + * See image_menu_item_set_image(). + * + * Return value: (transfer none): the widget set as image of @image_menu_item + * + **/ +GtkWidget* +image_menu_item_get_image (ImageMenuItem *image_menu_item) +{ + g_return_val_if_fail (IS_IMAGE_MENU_ITEM (image_menu_item), NULL); + + return image_menu_item->priv->image; +} + +static void +image_menu_item_remove (GtkContainer *container, + GtkWidget *child) +{ + ImageMenuItem *image_menu_item = IMAGE_MENU_ITEM (container); + ImageMenuItemPrivate *priv = image_menu_item->priv; + + if (child == priv->image) + { + gboolean widget_was_visible; + + widget_was_visible = gtk_widget_get_visible (child); + + gtk_widget_unparent (child); + priv->image = NULL; + + if (widget_was_visible && + gtk_widget_get_visible (GTK_WIDGET (container))) + gtk_widget_queue_resize (GTK_WIDGET (container)); + + g_object_notify (G_OBJECT (image_menu_item), "image"); + } + else + { + GTK_CONTAINER_CLASS (image_menu_item_parent_class)->remove (container, child); + } +} + +static void +show_image_change_notify (ImageMenuItem *image_menu_item) +{ + ImageMenuItemPrivate *priv = image_menu_item->priv; + + if (priv->image) + { + gtk_widget_show (priv->image); + } +} + +static void +traverse_container (GtkWidget *widget, + gpointer data) +{ + if (IS_IMAGE_MENU_ITEM (widget)) + show_image_change_notify (IMAGE_MENU_ITEM (widget)); + else if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL); +} + +static void +image_menu_item_setting_changed (GtkSettings *settings) +{ + GList *list, *l; + + list = gtk_window_list_toplevels (); + + for (l = list; l; l = l->next) + gtk_container_forall (GTK_CONTAINER (l->data), + traverse_container, NULL); + + g_list_free (list); +} + +static void +image_menu_item_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + GtkSettings *settings; + gulong show_image_connection; + + if (!gtk_widget_has_screen (widget)) + return; + + settings = gtk_widget_get_settings (widget); + + show_image_connection = + g_signal_handler_find (settings, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, image_menu_item_setting_changed, NULL); + + if (show_image_connection) + return; + + g_signal_connect (settings, "notify::gtk-menu-images", + G_CALLBACK (image_menu_item_setting_changed), NULL); + + show_image_change_notify (IMAGE_MENU_ITEM (widget)); +} diff --git a/src/widgets/image-menu-item.h b/src/widgets/image-menu-item.h new file mode 100644 index 000000000..61cc48f3a --- /dev/null +++ b/src/widgets/image-menu-item.h @@ -0,0 +1,81 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. + * Forked for , icons in menus are important to us. + */ + +#ifndef __IMAGE_MENU_ITEM_H__ +#define __IMAGE_MENU_ITEM_H__ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB +#define GTK_PARAM_WRITABLE G_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB +#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB + +#define TYPE_IMAGE_MENU_ITEM (image_menu_item_get_type ()) +#define IMAGE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_IMAGE_MENU_ITEM, ImageMenuItem)) +#define IMAGE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_IMAGE_MENU_ITEM, ImageMenuItemClass)) +#define IS_IMAGE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_IMAGE_MENU_ITEM)) +#define IS_IMAGE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_IMAGE_MENU_ITEM)) +#define IMAGE_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_IMAGE_MENU_ITEM, ImageMenuItemClass)) + +typedef struct _ImageMenuItem ImageMenuItem; +typedef struct _ImageMenuItemPrivate ImageMenuItemPrivate; +typedef struct _ImageMenuItemClass ImageMenuItemClass; + +struct _ImageMenuItem +{ + GtkMenuItem menu_item; + + /*< private >*/ + ImageMenuItemPrivate *priv; +}; + +struct _ImageMenuItemClass +{ + GtkMenuItemClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + +GType image_menu_item_get_type (void) G_GNUC_CONST; +GtkWidget* image_menu_item_new (void); +GtkWidget* image_menu_item_new_with_label (const gchar *label); +GtkWidget* image_menu_item_new_with_mnemonic (const gchar *label); +GtkWidget* image_menu_item_new_from_stock (const gchar *stock_id, + GtkAccelGroup *accel_group); +void image_menu_item_set_image (ImageMenuItem *image_menu_item, + GtkWidget *image); +GtkWidget* image_menu_item_get_image (ImageMenuItem *image_menu_item); +void image_menu_item_set_use_stock (ImageMenuItem *image_menu_item, + gboolean use_stock); +gboolean image_menu_item_get_use_stock (ImageMenuItem *image_menu_item); +void image_menu_item_set_accel_group (ImageMenuItem *image_menu_item, + GtkAccelGroup *accel_group); + +G_END_DECLS + +#endif /* __IMAGE_MENU_ITEM_H__ */ diff --git a/src/widgets/ink-action.cpp b/src/widgets/ink-action.cpp index 5941c31e4..ace99d9aa 100644 --- a/src/widgets/ink-action.cpp +++ b/src/widgets/ink-action.cpp @@ -1,12 +1,20 @@ #include "widgets/icon.h" #include "icon-size.h" #include <glib/gi18n.h> -#include <gtk/gtk.h> + #include "widgets/ink-action.h" #include "widgets/button.h" +#include <gtk/gtk.h> + +#if GTK_CHECK_VERSION(3,0,0) + // Fork of gtk-imagemenuitem to continue support + #include "widgets/image-menu-item.h" + +#endif + static void ink_action_finalize( GObject* obj ); static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ); static void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec ); @@ -158,7 +166,12 @@ static GtkWidget* ink_action_create_menu_item( GtkAction* action ) gchar* label = 0; g_object_get( G_OBJECT(act), "label", &label, NULL ); +#if GTK_CHECK_VERSION(3,0,0) + item = image_menu_item_new_with_mnemonic( label ); +#else item = gtk_image_menu_item_new_with_mnemonic( label ); +#endif + GtkWidget* child = sp_icon_new( Inkscape::ICON_SIZE_MENU, act->private_data->iconId ); // TODO this work-around is until SPIcon will live properly inside of a popup menu if ( SP_IS_ICON(child) ) { @@ -172,7 +185,12 @@ static GtkWidget* ink_action_create_menu_item( GtkAction* action ) } } gtk_widget_show_all( child ); + +#if GTK_CHECK_VERSION(3,0,0) + image_menu_item_set_image( IMAGE_MENU_ITEM(item), child ); +#else gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(item), child ); +#endif g_free( label ); label = 0; @@ -374,9 +392,16 @@ static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action ) GtkToolButton* button = GTK_TOOL_BUTTON(item); if ( act->private_data->iconId ) { GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId ); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_hexpand(child, FALSE); + gtk_widget_set_vexpand(child, FALSE); + gtk_tool_button_set_icon_widget(button, child); +#else GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 ); gtk_container_add( GTK_CONTAINER(align), child ); gtk_tool_button_set_icon_widget( button, align ); +#endif } else { gchar *label = 0; g_object_get( G_OBJECT(action), "short_label", &label, NULL ); @@ -405,10 +430,18 @@ static void ink_toggle_action_update_icon( InkToggleAction* action ) GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data); GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId ); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_hexpand(child, FALSE); + gtk_widget_set_vexpand(child, FALSE); + gtk_widget_show_all(child); + gtk_tool_button_set_icon_widget(button, child); +#else GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 ); gtk_container_add( GTK_CONTAINER(align), child ); gtk_widget_show_all( align ); gtk_tool_button_set_icon_widget( button, align ); +#endif } } @@ -577,9 +610,16 @@ static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action ) GtkToolButton* button = GTK_TOOL_BUTTON(item); GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId ); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_hexpand(child, FALSE); + gtk_widget_set_vexpand(child, FALSE); + gtk_tool_button_set_icon_widget(button, child); +#else GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 ); gtk_container_add( GTK_CONTAINER(align), child ); gtk_tool_button_set_icon_widget( button, align ); +#endif } else { // For now trigger a warning but don't do anything else GtkToolButton* button = GTK_TOOL_BUTTON(item); diff --git a/src/widgets/ink-comboboxentry-action.cpp b/src/widgets/ink-comboboxentry-action.cpp index 1114d2cdb..ec5e26cf5 100644 --- a/src/widgets/ink-comboboxentry-action.cpp +++ b/src/widgets/ink-comboboxentry-action.cpp @@ -371,9 +371,16 @@ GtkWidget* create_tool_item( GtkAction* action ) g_free( combobox_name ); { +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(comboBoxEntry, GTK_ALIGN_START); + gtk_widget_set_hexpand(comboBoxEntry, FALSE); + gtk_widget_set_vexpand(comboBoxEntry, FALSE); + gtk_container_add(GTK_CONTAINER(item), comboBoxEntry); +#else GtkWidget *align = gtk_alignment_new(0, 0.5, 0, 0); gtk_container_add( GTK_CONTAINER(align), comboBoxEntry ); gtk_container_add( GTK_CONTAINER(item), align ); +#endif } ink_comboboxentry_action->combobox = GTK_COMBO_BOX (comboBoxEntry); @@ -956,3 +963,14 @@ gboolean keypress_cb( GtkWidget * /*widget*/, GdkEventKey *event, gpointer data return wasConsumed; } + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp index ab486eeeb..deffd384a 100644 --- a/src/widgets/ruler.cpp +++ b/src/widgets/ruler.cpp @@ -41,8 +41,9 @@ #define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB -#define DEFAULT_RULER_FONT_SCALE PANGO_SCALE_X_SMALL -#define MINIMUM_INCR 5 +#define DEFAULT_RULER_FONT_SCALE PANGO_SCALE_X_SMALL +#define MINIMUM_INCR 5 +#define IMMEDIATE_REDRAW_THRESHOLD 20 using Inkscape::Util::unit_table; @@ -71,11 +72,11 @@ typedef struct GdkWindow *input_window; cairo_surface_t *backing_store; + gboolean backing_store_valid; + GdkRectangle last_pos_rect; + guint pos_redraw_idle_id; PangoLayout *layout; gdouble font_scale; - - gint xsrc; - gint ysrc; GList *track_widgets; } SPRulerPrivate; @@ -132,18 +133,22 @@ static void sp_ruler_style_updated (GtkWidget *widget); static void sp_ruler_size_request (GtkWidget *widget, GtkRequisition *requisition); static void sp_ruler_style_set (GtkWidget *widget, - GtkStyle *prev_style); + GtkStyle *prev_style); #endif static gboolean sp_ruler_motion_notify (GtkWidget *widget, GdkEventMotion *event); static gboolean sp_ruler_draw (GtkWidget *widget, - cairo_t *cr); + cairo_t *cr); #if !GTK_CHECK_VERSION(3,0,0) static gboolean sp_ruler_expose (GtkWidget *widget, GdkEventExpose *event); #endif static void sp_ruler_draw_ticks (SPRuler *ruler); +static GdkRectangle sp_ruler_get_pos_rect (SPRuler *ruler, + gdouble position); +static gboolean sp_ruler_idle_queue_pos_redraw(gpointer data); +static void sp_ruler_queue_pos_redraw (SPRuler *ruler); static void sp_ruler_draw_pos (SPRuler *ruler, cairo_t *cr); static void sp_ruler_make_pixmap (SPRuler *ruler); @@ -163,6 +168,10 @@ sp_ruler_class_init (SPRulerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); +#if GTK_CHECK_VERSION(3,20,0) + gtk_widget_class_set_css_name (widget_class, "ruler-widget"); +#endif + object_class->dispose = sp_ruler_dispose; object_class->set_property = sp_ruler_set_property; object_class->get_property = sp_ruler_get_property; @@ -260,34 +269,23 @@ sp_ruler_init (SPRuler *ruler) gtk_widget_set_has_window (GTK_WIDGET (ruler), FALSE); - priv->orientation = GTK_ORIENTATION_HORIZONTAL; - priv->unit = unit_table.getUnit("px"); - priv->lower = 0; - priv->upper = 0; - priv->position = 0; - priv->max_size = 0; - priv->backing_store = NULL; - priv->font_scale = DEFAULT_RULER_FONT_SCALE; + priv->orientation = GTK_ORIENTATION_HORIZONTAL; + priv->unit = unit_table.getUnit("px"); + priv->lower = 0; + priv->upper = 0; + priv->position = 0; + priv->max_size = 0; -#if GTK_CHECK_VERSION(3,0,0) - #if GTK_CHECK_VERSION(3,8,0) - const gchar *str = - "SPRuler {\n" - " background-color: @theme_bg_color;\n" - "}\n"; - #else - const gchar *str = - "SPRuler {\n" - " background-color: @bg_color;\n" - "}\n"; - #endif - GtkCssProvider *css = gtk_css_provider_new (); - gtk_css_provider_load_from_data (css, str, -1, NULL); - gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (ruler)), - GTK_STYLE_PROVIDER (css), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_object_unref (css); -#endif + priv->backing_store = NULL; + priv->backing_store_valid = FALSE; + + priv->last_pos_rect.x = 0; + priv->last_pos_rect.y = 0; + priv->last_pos_rect.width = 0; + priv->last_pos_rect.height = 0; + priv->pos_redraw_idle_id = 0; + + priv->font_scale = DEFAULT_RULER_FONT_SCALE; } static void @@ -299,6 +297,12 @@ sp_ruler_dispose (GObject *object) while (priv->track_widgets) sp_ruler_remove_track_widget (ruler, GTK_WIDGET(priv->track_widgets->data)); + if (priv->pos_redraw_idle_id) + { + g_source_remove (priv->pos_redraw_idle_id); + priv->pos_redraw_idle_id = 0; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -343,6 +347,7 @@ sp_ruler_set_range (SPRuler *ruler, } g_object_thaw_notify (G_OBJECT (ruler)); + priv->backing_store_valid = FALSE; gtk_widget_queue_draw (GTK_WIDGET (ruler)); } @@ -513,7 +518,9 @@ sp_ruler_unrealize(GtkWidget *widget) cairo_surface_destroy (priv->backing_store); priv->backing_store = NULL; } - + + priv->backing_store_valid = FALSE; + if (priv->layout) { g_object_unref (priv->layout); @@ -689,7 +696,6 @@ sp_ruler_expose (GtkWidget *widget, cairo_clip (cr); gtk_widget_get_allocation (widget, &allocation); - cairo_translate (cr, allocation.x, allocation.y); gboolean result = sp_ruler_draw (widget, cr); @@ -733,6 +739,8 @@ sp_ruler_make_pixmap (SPRuler *ruler) CAIRO_CONTENT_COLOR, allocation.width, allocation.height); + + priv->backing_store_valid = FALSE; } static void @@ -743,118 +751,22 @@ sp_ruler_draw_pos (SPRuler *ruler, #if GTK_CHECK_VERSION(3,0,0) GtkStyleContext *context = gtk_widget_get_style_context (widget); - GtkBorder border; GdkRGBA color; #else GtkStyle *style = gtk_widget_get_style (widget); GtkStateType state = gtk_widget_get_state (widget); - gint xthickness; - gint ythickness; #endif SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); - GtkAllocation allocation; - gint x, y; - gint width, height; - gint bs_width, bs_height; + GdkRectangle pos_rect; if (! gtk_widget_is_drawable (widget)) return; - gtk_widget_get_allocation(widget, &allocation); - -#if GTK_CHECK_VERSION(3,0,0) - gtk_style_context_get_border (context, static_cast<GtkStateFlags>(0), &border); -#else - xthickness = style->xthickness; - ythickness = style->ythickness; -#endif - - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) - { - width = allocation.width; -#if GTK_CHECK_VERSION(3,0,0) - height = allocation.height - (border.top + border.bottom); -#else - height = allocation.height - ythickness * 2; -#endif - - bs_width = height / 2 + 2; - bs_width |= 1; /* make sure it's odd */ - bs_height = bs_width / 2 + 1; - } - else - { -#if GTK_CHECK_VERSION(3,0,0) - width = allocation.width - (border.left + border.right); -#else - width = allocation.width - xthickness * 2; -#endif - height = allocation.height; - - bs_height = width / 2 + 2; - bs_height |= 1; /* make sure it's odd */ - bs_width = bs_height / 2 + 1; - } + pos_rect = sp_ruler_get_pos_rect (ruler, sp_ruler_get_position (ruler)); - if ((bs_width > 0) && (bs_height > 0)) + if ((pos_rect.width > 0) && (pos_rect.height > 0)) { - gdouble lower; - gdouble upper; - gdouble position; - gdouble increment; - - if (! cr) - { - cr = gdk_cairo_create (gtk_widget_get_window (widget)); - cairo_translate (cr, allocation.x, allocation.y); - cairo_rectangle (cr, allocation.x, allocation.y, allocation.width, allocation.height); - cairo_clip (cr); - - cairo_translate (cr, allocation.x, allocation.y); - - /* If a backing store exists, restore the ruler */ - if (priv->backing_store) - { - cairo_set_source_surface (cr, priv->backing_store, 0, 0); - cairo_rectangle (cr, priv->xsrc, priv->ysrc, bs_width, bs_height); - cairo_fill (cr); - } - } - else - { - cairo_reference (cr); - } - - position = sp_ruler_get_position (ruler); - - sp_ruler_get_range (ruler, &lower, &upper, NULL); - - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) - { - increment = (gdouble) width / (upper - lower); - -#if GTK_CHECK_VERSION(3,0,0) - x = ROUND ((position - lower) * increment) + (border.left - bs_width) / 2 - 1; - y = (height + bs_height) / 2 + border.top; -#else - x = ROUND ((position - lower) * increment) + (xthickness - bs_width) / 2 - 1; - y = (height + bs_height) / 2 + ythickness; -#endif - } - else - { - increment = (gdouble) height / (upper - lower); - -#if GTK_CHECK_VERSION(3,0,0) - x = (width + bs_width) / 2 + border.left; - y = ROUND ((position - lower) * increment) + (border.top - bs_height) / 2 - 1; -#else - x = (width + bs_width) / 2 + xthickness; - y = ROUND ((position - lower) * increment) + (ythickness - bs_height) / 2 - 1; -#endif - } - #if GTK_CHECK_VERSION(3,0,0) gtk_style_context_get_color (context, gtk_widget_get_state_flags (widget), &color); @@ -863,26 +775,28 @@ sp_ruler_draw_pos (SPRuler *ruler, gdk_cairo_set_source_color (cr, &style->fg[state]); #endif - cairo_move_to (cr, x, y); + cairo_move_to (cr, pos_rect.x, pos_rect.y); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { - cairo_line_to (cr, x + bs_width / 2.0, y + bs_height); - cairo_line_to (cr, x + bs_width, y); + cairo_line_to (cr, pos_rect.x + pos_rect.width / 2.0, + pos_rect.y + pos_rect.height); + cairo_line_to (cr, pos_rect.x + pos_rect.width, + pos_rect.y); } else { - cairo_line_to (cr, x + bs_width, y + bs_height / 2.0); - cairo_line_to (cr, x, y + bs_height); + cairo_line_to (cr, pos_rect.x + pos_rect.width, + + pos_rect.y + pos_rect.height / 2.0); + cairo_line_to (cr, pos_rect.x, + pos_rect.y + pos_rect.height); } cairo_fill (cr); - - cairo_destroy (cr); - - priv->xsrc = x; - priv->ysrc = y; } + + priv->last_pos_rect = pos_rect; } /** @@ -1096,6 +1010,7 @@ sp_ruler_set_unit (SPRuler *ruler, priv->unit = unit; g_object_notify(G_OBJECT(ruler), "unit"); + priv->backing_store_valid = FALSE; gtk_widget_queue_draw (GTK_WIDGET (ruler)); } } @@ -1131,10 +1046,39 @@ sp_ruler_set_position (SPRuler *ruler, if (priv->position != position) { - priv->position = position; - g_object_notify (G_OBJECT (ruler), "position"); - - sp_ruler_draw_pos (ruler, NULL); + GdkRectangle rect; + gint xdiff, ydiff; + + priv->position = position; + g_object_notify (G_OBJECT (ruler), "position"); + + rect = sp_ruler_get_pos_rect (ruler, priv->position); + + xdiff = rect.x - priv->last_pos_rect.x; + ydiff = rect.y - priv->last_pos_rect.y; + + /* + * If the position has changed far enough, queue a redraw immediately. + * Otherwise, we only queue a redraw in a low priority idle handler, to + * allow for other things (like updating the canvas) to run. + * + * TODO: This might not be necessary any more in GTK3 with the frame + * clock. Investigate this more after the port to GTK3. + */ + if (priv->last_pos_rect.width != 0 && + priv->last_pos_rect.height != 0 && + (ABS (xdiff) > IMMEDIATE_REDRAW_THRESHOLD || + ABS (ydiff) > IMMEDIATE_REDRAW_THRESHOLD)) + { + sp_ruler_queue_pos_redraw (ruler); + } + else if (! priv->pos_redraw_idle_id) + { + priv->pos_redraw_idle_id = + g_idle_add_full (G_PRIORITY_LOW, + sp_ruler_idle_queue_pos_redraw, + ruler, NULL); + } } } @@ -1154,7 +1098,7 @@ sp_ruler_get_position (SPRuler *ruler) static gboolean sp_ruler_motion_notify (GtkWidget *widget, - GdkEventMotion *event) + GdkEventMotion *event) { SPRuler *ruler = SP_RULER(widget); @@ -1347,7 +1291,7 @@ sp_ruler_draw_ticks (SPRuler *ruler) if (ideal_length > ++length) length = ideal_length; - if (lower < upper) + if (lower < upper) { start = floor (lower / subd_incr) * subd_incr; end = ceil (upper / subd_incr) * subd_incr; @@ -1413,16 +1357,16 @@ sp_ruler_draw_ticks (SPRuler *ruler) pango_layout_get_extents (layout, &logical_rect, NULL); #if GTK_CHECK_VERSION(3,0,0) - cairo_move_to (cr, + cairo_move_to (cr, pos + 2, border.top + PANGO_PIXELS (logical_rect.y - digit_offset)); #else - cairo_move_to (cr, + cairo_move_to (cr, pos + 2, ythickness + PANGO_PIXELS (logical_rect.y - digit_offset)); #endif - pango_cairo_show_layout(cr, layout); + pango_cairo_show_layout(cr, layout); } else { @@ -1435,15 +1379,15 @@ sp_ruler_draw_ticks (SPRuler *ruler) pango_layout_get_extents (layout, NULL, &logical_rect); #if GTK_CHECK_VERSION(3,0,0) - cairo_move_to (cr, + cairo_move_to (cr, border.left + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset)); #else - cairo_move_to (cr, + cairo_move_to (cr, xthickness + 1, pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset)); #endif - pango_cairo_show_layout (cr, layout); + pango_cairo_show_layout (cr, layout); } } } @@ -1454,10 +1398,128 @@ sp_ruler_draw_ticks (SPRuler *ruler) cairo_fill (cr); + priv->backing_store_valid = TRUE; + out: cairo_destroy (cr); } +static GdkRectangle +sp_ruler_get_pos_rect (SPRuler *ruler, + gdouble position) +{ + GtkWidget *widget = GTK_WIDGET (ruler); + SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); + GtkAllocation allocation; + gint width, height; + gint xthickness; + gint ythickness; + gdouble upper, lower; + gdouble increment; + GdkRectangle rect = { 0, 0, 0, 0 }; + + if (! gtk_widget_is_drawable (widget)) + return rect; + + gtk_widget_get_allocation (widget, &allocation); + +#if GTK_CHECK_VERSION(3,0,0) + GtkStyleContext *context = gtk_widget_get_style_context (widget); + GtkBorder padding; + + gtk_style_context_get_border(context, static_cast<GtkStateFlags>(0), &padding); + + xthickness = padding.left + padding.right; + ythickness = padding.top + padding.bottom; +#else + GtkStyle *style = gtk_widget_get_style (widget); + xthickness = style->xthickness; + ythickness = style->ythickness; +#endif + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + width = allocation.width; + height = allocation.height - ythickness * 2; + + rect.width = height / 2 + 2; + rect.width |= 1; /* make sure it's odd */ + rect.height = rect.width / 2 + 1; + } + else + { + width = allocation.width - xthickness * 2; + height = allocation.height; + + rect.height = width / 2 + 2; + rect.height |= 1; /* make sure it's odd */ + rect.width = rect.height / 2 + 1; + } + + sp_ruler_get_range (ruler, &lower, &upper, NULL); + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + increment = (gdouble) width / (upper - lower); + + rect.x = ROUND ((position - lower) * increment) + (xthickness - rect.width) / 2 - 1; + rect.y = (height + rect.height) / 2 + ythickness; + } + else + { + increment = (gdouble) height / (upper - lower); + + rect.x = (width + rect.width) / 2 + xthickness; + rect.y = ROUND ((position - lower) * increment) + (ythickness - rect.height) / 2 - 1; + } + + rect.x += allocation.x; + rect.y += allocation.y; + + return rect; +} + +static gboolean +sp_ruler_idle_queue_pos_redraw (gpointer data) +{ + SPRuler *ruler = (SPRuler *)data; + SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); + + sp_ruler_queue_pos_redraw (ruler); + + gboolean ret = g_source_remove(priv->pos_redraw_idle_id); + priv->pos_redraw_idle_id = 0; + + return ret; +} + +static void +sp_ruler_queue_pos_redraw (SPRuler *ruler) +{ + SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); + const GdkRectangle rect = sp_ruler_get_pos_rect (ruler, priv->position); + + gtk_widget_queue_draw_area (GTK_WIDGET(ruler), + rect.x, + rect.y, + rect.width, + rect.height); + + if (priv->last_pos_rect.width != 0 || priv->last_pos_rect.height != 0) + { + gtk_widget_queue_draw_area (GTK_WIDGET(ruler), + priv->last_pos_rect.x, + priv->last_pos_rect.y, + priv->last_pos_rect.width, + priv->last_pos_rect.height); + + priv->last_pos_rect.x = 0; + priv->last_pos_rect.y = 0; + priv->last_pos_rect.width = 0; + priv->last_pos_rect.height = 0; + } +} + static PangoLayout* sp_ruler_create_layout (GtkWidget *widget, const gchar *text) diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index e49c4c00a..9851b0606 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -136,13 +136,13 @@ sp_selection_layout_widget_change_selection(SPWidget *spw, Inkscape::Selection * } static void -sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) +sp_object_layout_any_value_changed(GtkAdjustment *adj, GObject *tbl) { - if (g_object_get_data(G_OBJECT(spw), "update")) { + if (g_object_get_data(tbl, "update")) { return; } - UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(G_OBJECT(spw), "tracker")); + UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker")); if ( !tracker || tracker->isUpdating() ) { /* * When only units are being changed, don't treat changes @@ -150,7 +150,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) */ return; } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(TRUE)); + g_object_set_data(tbl, "update", GINT_TO_POINTER(TRUE)); SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::Selection *selection = desktop->getSelection(); @@ -168,7 +168,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) Geom::OptRect bbox_user = selection->bounds(bbox_type); if ( !bbox_user ) { - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); + g_object_set_data(tbl, "update", GINT_TO_POINTER(FALSE)); return; } @@ -181,10 +181,10 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) Unit const *unit = tracker->getActiveUnit(); g_return_if_fail(unit != NULL); - GtkAdjustment* a_x = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "X" ) ); - GtkAdjustment* a_y = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "Y" ) ); - GtkAdjustment* a_w = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "width" ) ); - GtkAdjustment* a_h = GTK_ADJUSTMENT( g_object_get_data( G_OBJECT(spw), "height" ) ); + GtkAdjustment* a_x = GTK_ADJUSTMENT( g_object_get_data( tbl, "X" ) ); + GtkAdjustment* a_y = GTK_ADJUSTMENT( g_object_get_data( tbl, "Y" ) ); + GtkAdjustment* a_w = GTK_ADJUSTMENT( g_object_get_data( tbl, "width" ) ); + GtkAdjustment* a_h = GTK_ADJUSTMENT( g_object_get_data( tbl, "height" ) ); if (unit->type == Inkscape::Util::UNIT_TYPE_LINEAR) { x0 = Quantity::convert(gtk_adjustment_get_value(a_x), unit, "px"); @@ -205,7 +205,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) } // Keep proportions if lock is on - GtkToggleAction *lock = GTK_TOGGLE_ACTION( g_object_get_data(G_OBJECT(spw), "lock") ); + GtkToggleAction *lock = GTK_TOGGLE_ACTION( g_object_get_data(tbl, "lock") ); if ( gtk_toggle_action_get_active(lock) ) { if (adj == a_h) { x1 = x0 + yrel * bbox_user->dimensions()[Geom::X]; @@ -265,68 +265,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) desktop->getCanvas()->endForcedFullRedraws(); } - g_object_set_data(G_OBJECT(spw), "update", GINT_TO_POINTER(FALSE)); -} - -static GtkWidget* createCustomSlider( GtkAdjustment *adjustment, gdouble climbRate, guint digits, Inkscape::UI::Widget::UnitTracker *unit_tracker ) -{ -#if WITH_GTKMM_3_0 - Glib::RefPtr<Gtk::Adjustment> adj = Glib::wrap(adjustment, true); - Inkscape::UI::Widget::SpinButton *inkSpinner = new Inkscape::UI::Widget::SpinButton(adj, climbRate, digits); -#else - Inkscape::UI::Widget::SpinButton *inkSpinner = new Inkscape::UI::Widget::SpinButton(*Glib::wrap(adjustment, true), climbRate, digits); -#endif - inkSpinner->addUnitTracker(unit_tracker); - inkSpinner = Gtk::manage( inkSpinner ); - GtkWidget *widget = GTK_WIDGET( inkSpinner->gobj() ); - return widget; -} - -// TODO create_adjustment_action appears to be a rogue tile copy from toolbox.cpp. Resolve it to be unified: - -static EgeAdjustmentAction * create_adjustment_action( gchar const *name, - gchar const *label, - gchar const *shortLabel, - gchar const *data, - gdouble lower, - GtkWidget* focusTarget, - UnitTracker* tracker, - GtkWidget* spw, - gchar const *tooltip, - gboolean altx ) -{ - static bool init = false; - if ( !init ) { - init = true; - ege_adjustment_action_set_compact_tool_factory( createCustomSlider ); - } - - GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( 0.0, lower, 1e6, SPIN_STEP, SPIN_PAGE_STEP, 0 ) ); - if (tracker) { - tracker->addAdjustment(adj); - } - if ( spw ) { - g_object_set_data( G_OBJECT(spw), data, adj ); - } - - EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, Q_(label), tooltip, 0, SPIN_STEP, 3, tracker ); - if ( shortLabel ) { - g_object_set( act, "short_label", Q_(shortLabel), NULL ); - } - - g_signal_connect( G_OBJECT(adj), "value_changed", G_CALLBACK(sp_object_layout_any_value_changed), spw ); - if ( focusTarget ) { - ege_adjustment_action_set_focuswidget( act, focusTarget ); - } - - if ( altx ) { // this spinbutton will be activated by alt-x - g_object_set( G_OBJECT(act), "self-id", "altx", NULL ); - } - - // Using a cast just to make sure we pass in the right kind of function pointer - g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL ); - - return act; + g_object_set_data(tbl, "update", GINT_TO_POINTER(FALSE)); } // toggle button callbacks and updaters @@ -497,21 +436,60 @@ void sp_select_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb // four spinbuttons - eact = create_adjustment_action( "XAction", C_("Select toolbar", "X position"), C_("Select toolbar", "X:"), "X", - -1e6, GTK_WIDGET(desktop->canvas), tracker, spw, - _("Horizontal coordinate of selection"), TRUE ); + eact = create_adjustment_action( + "XAction", /* name */ + C_("Select toolbar", "X position"), /* label */ + C_("Select toolbar", "X:"), /* shortLabel */ + C_("Select toolbar", "Horizontal coordinate of selection"), /* tooltip */ + "/tools/select/X", /* path */ + 0.0, /* def(default) */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + G_OBJECT(spw), /* dataKludge */ + TRUE, "altx", /* altx, altx_mark */ + -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP, /* lower, uppper, step, page */ + 0, 0, 0, /* descrLabels, descrValues, descrCount */ + sp_object_layout_any_value_changed, /* callback */ + tracker, /* unit_tracker */ + SPIN_STEP, 3, 1); /* climb, digits, factor */ + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); contextActions->push_back( GTK_ACTION(eact) ); - eact = create_adjustment_action( "YAction", C_("Select toolbar", "Y position"), C_("Select toolbar", "Y:"), "Y", - -1e6, GTK_WIDGET(desktop->canvas), tracker, spw, - _("Vertical coordinate of selection"), FALSE ); + eact = create_adjustment_action( + "YAction", /* name */ + C_("Select toolbar", "Y position"), /* label */ + C_("Select toolbar", "Y:"), /* shortLabel */ + C_("Select toolbar", "Vertical coordinate of selection"), /* tooltip */ + "/tools/select/Y", /* path */ + 0.0, /* def(default) */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + G_OBJECT(spw), /* dataKludge */ + TRUE, "altx", /* altx, altx_mark */ + -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP, /* lower, uppper, step, page */ + 0, 0, 0, /* descrLabels, descrValues, descrCount */ + sp_object_layout_any_value_changed, /* callback */ + tracker, /* unit_tracker */ + SPIN_STEP, 3, 1); /* climb, digits, factor */ + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); contextActions->push_back( GTK_ACTION(eact) ); - eact = create_adjustment_action( "WidthAction", C_("Select toolbar", "Width"), C_("Select toolbar", "W:"), "width", - 0.0, GTK_WIDGET(desktop->canvas), tracker, spw, - _("Width of selection"), FALSE ); + eact = create_adjustment_action( + "WidthAction", /* name */ + C_("Select toolbar", "Width"), /* label */ + C_("Select toolbar", "W:"), /* shortLabel */ + C_("Select toolbar", "Width of selection"), /* tooltip */ + "/tools/select/width", /* path */ + 0.0, /* def(default) */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + G_OBJECT(spw), /* dataKludge */ + TRUE, "altx", /* altx, altx_mark */ + 0.0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, /* lower, uppper, step, page */ + 0, 0, 0, /* descrLabels, descrValues, descrCount */ + sp_object_layout_any_value_changed, /* callback */ + tracker, /* unit_tracker */ + SPIN_STEP, 3, 1); /* climb, digits, factor */ + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); contextActions->push_back( GTK_ACTION(eact) ); @@ -528,9 +506,23 @@ void sp_select_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb gtk_action_group_add_action( mainActions, GTK_ACTION(itact) ); } - eact = create_adjustment_action( "HeightAction", C_("Select toolbar", "Height"), C_("Select toolbar", "H:"), "height", - 0.0, GTK_WIDGET(desktop->canvas), tracker, spw, - _("Height of selection"), FALSE ); + eact = create_adjustment_action( + "HeightAction", /* name */ + C_("Select toolbar", "Height"), /* label */ + C_("Select toolbar", "H:"), /* shortLabel */ + C_("Select toolbar", "Height of selection"), /* tooltip */ + "/tools/select/height", /* path */ + 0.0, /* def(default) */ + GTK_WIDGET(desktop->canvas), /* focusTarget */ + G_OBJECT(spw), /* dataKludge */ + TRUE, "altx", /* altx, altx_mark */ + 0.0, 1e6, SPIN_STEP, SPIN_PAGE_STEP, /* lower, uppper, step, page */ + 0, 0, 0, /* descrLabels, descrValues, descrCount */ + sp_object_layout_any_value_changed, /* callback */ + tracker, /* unit_tracker */ + SPIN_STEP, 3, 1); /* climb, digits, factor */ + + gtk_action_group_add_action( selectionActions, GTK_ACTION(eact) ); contextActions->push_back( GTK_ACTION(eact) ); diff --git a/src/widgets/shrink-wrap-button.cpp b/src/widgets/shrink-wrap-button.cpp deleted file mode 100644 index 941a0466c..000000000 --- a/src/widgets/shrink-wrap-button.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Inkscape::Widgets::shrink_wrap_button - shrink a button to minimum size - * - * Authors: - * MenTaLguY <mental@rydia.net> - * - * Copyright (C) 2004 MenTaLguY - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gtkmm/button.h> -#include <gtk/gtk.h> - -#include "shrink-wrap-button.h" - -namespace Inkscape { -namespace Widgets { - -void shrink_wrap_button(Gtk::Button &button) { - button.set_border_width(0); - button.set_can_focus(false); - button.set_can_default(false); - - Gtk::Widget* child = button.get_child(); - Gtk::Requisition req_min; - - if (child) { -#if WITH_GTKMM_3_0 - Gtk::Requisition req_nat; - child->get_preferred_size(req_min, req_nat); -#else - req_min = child->size_request(); -#endif - } else { - req_min.width = 0; - req_min.height = 0; - } - - // TODO: Use Gtk::StyleContext instead - GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(button.gobj())); - - req_min.width += 2 + 2 * std::max(2, style->xthickness); - req_min.height += 2 + 2 * std::max(2, style->ythickness); - - button.set_size_request(req_min.width, req_min.height); -} - -} -} - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/widgets/shrink-wrap-button.h b/src/widgets/shrink-wrap-button.h deleted file mode 100644 index ca9153aea..000000000 --- a/src/widgets/shrink-wrap-button.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Inkscape::Widgets::shrink_wrap_button - shrink a button to minimum size - * - * Authors: - * MenTaLguY <mental@rydia.net> - * - * Copyright (C) 2004 MenTaLguY - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifndef SEEN_INKSCAPE_WIDGETS_SHRINK_WRAP_BUTTON_H -#define SEEN_INKSCAPE_WIDGETS_SHRINK_WRAP_BUTTON_H - -namespace Gtk { class Button; } - -namespace Inkscape { -namespace Widgets { - -void shrink_wrap_button(Gtk::Button &button); - -} -} - -#endif -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp index 7030753a5..5500e1068 100644 --- a/src/widgets/spw-utilities.cpp +++ b/src/widgets/spw-utilities.cpp @@ -84,12 +84,23 @@ spw_label_old(GtkWidget *table, const gchar *label_text, int col, int row) label_widget = gtk_label_new (label_text); g_assert(label_widget != NULL); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(label_widget, GTK_ALIGN_END); +#else gtk_misc_set_alignment (GTK_MISC (label_widget), 1.0, 0.5); +#endif + gtk_widget_show (label_widget); #if GTK_CHECK_VERSION(3,0,0) +#if GTK_CHECK_VERSION(3,12,0) + gtk_widget_set_margin_start(label_widget, 4); + gtk_widget_set_margin_end(label_widget, 4); +#else gtk_widget_set_margin_left(label_widget, 4); gtk_widget_set_margin_right(label_widget, 4); +#endif gtk_widget_set_hexpand(label_widget, TRUE); gtk_widget_set_halign(label_widget, GTK_ALIGN_FILL); gtk_widget_set_valign(label_widget, GTK_ALIGN_CENTER); @@ -166,7 +177,13 @@ spw_checkbutton(GtkWidget * dialog, GtkWidget * table, g_assert(table != NULL); GtkWidget *l = gtk_label_new (label); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(l, GTK_ALIGN_END); +#else gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5); +#endif + gtk_widget_show (l); #if GTK_CHECK_VERSION(3,0,0) @@ -238,12 +255,26 @@ sp_set_font_size_recursive (GtkWidget *w, gpointer font) { guint size = GPOINTER_TO_UINT (font); - PangoFontDescription* pan = pango_font_description_new (); - pango_font_description_set_size (pan, size); - #if GTK_CHECK_VERSION(3,0,0) - gtk_widget_override_font (w, pan); + GtkCssProvider *css_provider = gtk_css_provider_new(); + + const double pt_size = size / static_cast<double>(PANGO_SCALE); + std::ostringstream css_data; + css_data << "GtkWidget {\n" + << " font-size: " << pt_size << "pt;\n" + << "}\n"; + + gtk_css_provider_load_from_data(css_provider, + css_data.str().c_str(), + -1, NULL); + + GtkStyleContext *style_context = gtk_widget_get_style_context(w); + gtk_style_context_add_provider(style_context, + GTK_STYLE_PROVIDER(css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); #else + PangoFontDescription* pan = pango_font_description_new (); + pango_font_description_set_size (pan, size); gtk_widget_modify_font (w, pan); #endif @@ -251,7 +282,11 @@ sp_set_font_size_recursive (GtkWidget *w, gpointer font) gtk_container_foreach (GTK_CONTAINER(w), (GtkCallback) sp_set_font_size_recursive, font); } +#if GTK_CHECK_VERSION(3,0,0) + g_object_unref(css_provider); +#else pango_font_description_free (pan); +#endif } void diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 43dffec56..84a6e77ad 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -221,6 +221,67 @@ StrokeStyle::StrokeStyle() : #endif i++; + /* Dash */ + spw_label(table, _("Dashes:"), 0, i, NULL); //no mnemonic for now + //decide what to do: + // implement a set_mnemonic_source function in the + // SPDashSelector class, so that we do not have to + // expose any of the underlying widgets? + dashSelector = Gtk::manage(new SPDashSelector); + + dashSelector->show(); + +#if WITH_GTKMM_3_0 + dashSelector->set_hexpand(); + dashSelector->set_halign(Gtk::ALIGN_FILL); + dashSelector->set_valign(Gtk::ALIGN_CENTER); + table->attach(*dashSelector, 1, i, 3, 1); +#else + table->attach(*dashSelector, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0); +#endif + + dashSelector->changed_signal.connect(sigc::mem_fun(*this, &StrokeStyle::lineDashChangedCB)); + + i++; + + /* Drop down marker selectors*/ + // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes + // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path. + + spw_label(table, _("Markers:"), 0, i, NULL); + + hb = spw_hbox(table, 1, 1, i); + i++; + + startMarkerCombo = Gtk::manage(new MarkerComboBox("marker-start", SP_MARKER_LOC_START)); + startMarkerCombo->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape")); + startMarkerConn = startMarkerCombo->signal_changed().connect( + sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( + sigc::ptr_fun(&StrokeStyle::markerSelectCB), startMarkerCombo, this, SP_MARKER_LOC_START)); + startMarkerCombo->show(); + + hb->pack_start(*startMarkerCombo, true, true, 0); + + midMarkerCombo = Gtk::manage(new MarkerComboBox("marker-mid", SP_MARKER_LOC_MID)); + midMarkerCombo->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes")); + midMarkerConn = midMarkerCombo->signal_changed().connect( + sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( + sigc::ptr_fun(&StrokeStyle::markerSelectCB), midMarkerCombo, this, SP_MARKER_LOC_MID)); + midMarkerCombo->show(); + + hb->pack_start(*midMarkerCombo, true, true, 0); + + endMarkerCombo = Gtk::manage(new MarkerComboBox("marker-end", SP_MARKER_LOC_END)); + endMarkerCombo->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape")); + endMarkerConn = endMarkerCombo->signal_changed().connect( + sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( + sigc::ptr_fun(&StrokeStyle::markerSelectCB), endMarkerCombo, this, SP_MARKER_LOC_END)); + endMarkerCombo->show(); + + hb->pack_start(*endMarkerCombo, true, true, 0); + + i++; + /* Join type */ // TRANSLATORS: The line join style specifies the shape to be used at the // corners of paths. It can be "miter", "round" or "bevel". @@ -230,14 +291,6 @@ StrokeStyle::StrokeStyle() : Gtk::RadioButtonGroup joinGrp; - joinMiter = makeRadioButton(joinGrp, INKSCAPE_ICON("stroke-join-miter"), - hb, STROKE_STYLE_BUTTON_JOIN, "miter"); - - // TRANSLATORS: Miter join: joining lines with a sharp (pointed) corner. - // For an example, draw a triangle with a large stroke width and modify the - // "Join" option (in the Fill and Stroke dialog). - joinMiter->set_tooltip_text(_("Miter join")); - joinRound = makeRadioButton(joinGrp, INKSCAPE_ICON("stroke-join-round"), hb, STROKE_STYLE_BUTTON_JOIN, "round"); @@ -254,7 +307,13 @@ StrokeStyle::StrokeStyle() : // "Join" option (in the Fill and Stroke dialog). joinBevel->set_tooltip_text(_("Bevel join")); - i++; + joinMiter = makeRadioButton(joinGrp, INKSCAPE_ICON("stroke-join-miter"), + hb, STROKE_STYLE_BUTTON_JOIN, "miter"); + + // TRANSLATORS: Miter join: joining lines with a sharp (pointed) corner. + // For an example, draw a triangle with a large stroke width and modify the + // "Join" option (in the Fill and Stroke dialog). + joinMiter->set_tooltip_text(_("Miter join")); /* Miterlimit */ // TRANSLATORS: Miter limit: only for "miter join", this limits the length @@ -265,8 +324,6 @@ StrokeStyle::StrokeStyle() : // when they become too long. //spw_label(t, _("Miter _limit:"), 0, i); - hb = spw_hbox(table, 3, 1, i); - #if WITH_GTKMM_3_0 miterLimitAdj = new Glib::RefPtr<Gtk::Adjustment>(Gtk::Adjustment::create(4.0, 0.0, 100.0, 0.1, 10.0, 0.0)); miterLimitSpin = new Inkscape::UI::Widget::SpinButton(*miterLimitAdj, 0.1, 2); @@ -277,7 +334,6 @@ StrokeStyle::StrokeStyle() : miterLimitSpin->set_tooltip_text(_("Maximum length of the miter (in units of stroke width)")); miterLimitSpin->show(); - spw_label(table, _("Miter _limit:"), 0, i, miterLimitSpin); sp_dialog_defocus_on_enter_cpp(miterLimitSpin); hb->pack_start(*miterLimitSpin, false, false, 0); @@ -288,6 +344,7 @@ StrokeStyle::StrokeStyle() : #else miterLimitAdj->signal_value_changed().connect(sigc::mem_fun(*this, &StrokeStyle::miterLimitChangedCB)); #endif + i++; /* Cap type */ @@ -322,64 +379,43 @@ StrokeStyle::StrokeStyle() : i++; - /* Dash */ - spw_label(table, _("Dashes:"), 0, i, NULL); //no mnemonic for now - //decide what to do: - // implement a set_mnemonic_source function in the - // SPDashSelector class, so that we do not have to - // expose any of the underlying widgets? - dashSelector = Gtk::manage(new SPDashSelector); - - dashSelector->show(); + /* Paint order */ + // TRANSLATORS: Paint order determines the order the 'fill', 'stroke', and 'markers are painted. + spw_label(table, _("Order:"), 0, i, NULL); -#if WITH_GTKMM_3_0 - dashSelector->set_hexpand(); - dashSelector->set_halign(Gtk::ALIGN_FILL); - dashSelector->set_valign(Gtk::ALIGN_CENTER); - table->attach(*dashSelector, 1, i, 3, 1); -#else - table->attach(*dashSelector, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast<Gtk::AttachOptions>(0), 0, 0); -#endif + hb = spw_hbox(table, 4, 1, i); - dashSelector->changed_signal.connect(sigc::mem_fun(*this, &StrokeStyle::lineDashChangedCB)); + Gtk::RadioButtonGroup paintOrderGrp; - i++; + paintOrderFSM = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-fsm"), + hb, STROKE_STYLE_BUTTON_ORDER, "normal"); + paintOrderFSM->set_tooltip_text(_("Fill, Stroke, Markers")); - /* Drop down marker selectors*/ - // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes - // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path. + paintOrderSFM = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-sfm"), + hb, STROKE_STYLE_BUTTON_ORDER, "stroke fill markers"); + paintOrderSFM->set_tooltip_text(_("Stroke, Fill, Markers")); - spw_label(table, _("Markers:"), 0, i, NULL); + paintOrderFMS = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-fms"), + hb, STROKE_STYLE_BUTTON_ORDER, "fill markers stroke"); + paintOrderFMS->set_tooltip_text(_("Fill, Markers, Stroke")); - hb = spw_hbox(table, 1, 1, i); i++; - startMarkerCombo = Gtk::manage(new MarkerComboBox("marker-start", SP_MARKER_LOC_START)); - startMarkerCombo->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape")); - startMarkerConn = startMarkerCombo->signal_changed().connect( - sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( - sigc::ptr_fun(&StrokeStyle::markerSelectCB), startMarkerCombo, this, SP_MARKER_LOC_START)); - startMarkerCombo->show(); + hb = spw_hbox(table, 4, 1, i); - hb->pack_start(*startMarkerCombo, true, true, 0); + paintOrderMFS = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-mfs"), + hb, STROKE_STYLE_BUTTON_ORDER, "markers fill stroke"); + paintOrderMFS->set_tooltip_text(_("Markers, Fill, Stroke")); - midMarkerCombo = Gtk::manage(new MarkerComboBox("marker-mid", SP_MARKER_LOC_MID)); - midMarkerCombo->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes")); - midMarkerConn = midMarkerCombo->signal_changed().connect( - sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( - sigc::ptr_fun(&StrokeStyle::markerSelectCB), midMarkerCombo, this, SP_MARKER_LOC_MID)); - midMarkerCombo->show(); + paintOrderSMF = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-smf"), + hb, STROKE_STYLE_BUTTON_ORDER, "stroke markers fill"); + paintOrderSMF->set_tooltip_text(_("Stroke, Markers, Fill")); - hb->pack_start(*midMarkerCombo, true, true, 0); + paintOrderMSF = makeRadioButton(paintOrderGrp, INKSCAPE_ICON("paint-order-msf"), + hb, STROKE_STYLE_BUTTON_ORDER, "markers stroke fill"); + paintOrderMSF->set_tooltip_text(_("Markers, Stroke, Fill")); - endMarkerCombo = Gtk::manage(new MarkerComboBox("marker-end", SP_MARKER_LOC_END)); - endMarkerCombo->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape")); - endMarkerConn = endMarkerCombo->signal_changed().connect( - sigc::bind<MarkerComboBox *, StrokeStyle *, SPMarkerLoc>( - sigc::ptr_fun(&StrokeStyle::markerSelectCB), endMarkerCombo, this, SP_MARKER_LOC_END)); - endMarkerCombo->show(); - - hb->pack_start(*endMarkerCombo, true, true, 0); + i++; setDesktop(desktop); updateLine(); @@ -802,6 +838,43 @@ StrokeStyle::setCapType (unsigned const captype) } /** + * Sets the cap type for a line, and updates the stroke style widget's buttons + */ +void +StrokeStyle::setPaintOrder (gchar const *paint_order) +{ + Gtk::RadioButton *tb = paintOrderFSM; + + SPIPaintOrder temp; + temp.read( paint_order ); + + if (temp.layer[0] != SP_CSS_PAINT_ORDER_NORMAL) { + + if (temp.layer[0] == SP_CSS_PAINT_ORDER_FILL) { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_STROKE) { + tb = paintOrderFSM; + } else { + tb = paintOrderFMS; + } + } else if (temp.layer[0] == SP_CSS_PAINT_ORDER_STROKE) { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_FILL) { + tb = paintOrderSFM; + } else { + tb = paintOrderSMF; + } + } else { + if (temp.layer[1] == SP_CSS_PAINT_ORDER_STROKE) { + tb = paintOrderMSF; + } else { + tb = paintOrderMFS; + } + } + + } + setPaintOrderButtons(tb); +} + +/** * Callback for when stroke style widget is updated, including markers, cap type, * join type, etc. */ @@ -825,6 +898,9 @@ StrokeStyle::updateLine() int result_ml = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_STROKEMITERLIMIT); int result_cap = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_STROKECAP); int result_join = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_STROKEJOIN); + + int result_order = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_PAINTORDER); + SPIPaint &targPaint = (kind == FILL) ? query.fill : query.stroke; if (!sel || sel->isEmpty()) { @@ -902,6 +978,13 @@ StrokeStyle::updateLine() setCapButtons(NULL); } + if (result_order != QUERY_STYLE_MULTIPLE_DIFFERENT && + result_order != QUERY_STYLE_NOTHING ) { + setPaintOrder (query.paint_order.value); + } else { + setPaintOrder (NULL); + } + if (!sel || sel->isEmpty()) return; @@ -1109,6 +1192,11 @@ void StrokeStyle::buttonToggledCB(StrokeStyleButton *tb, StrokeStyle *spw) sp_repr_css_set_property(css, "stroke-linecap", tb->get_stroke_style()); sp_desktop_set_style (spw->desktop, css); spw->setCapButtons(tb); + break; + case STROKE_STYLE_BUTTON_ORDER: + sp_repr_css_set_property(css, "paint-order", tb->get_stroke_style()); + sp_desktop_set_style (spw->desktop, css); + //spw->setPaintButtons(tb); } sp_repr_css_attr_unref(css); @@ -1143,6 +1231,21 @@ StrokeStyle::setCapButtons(Gtk::ToggleButton *active) /** + * Updates the paint order style toggle buttons + */ +void +StrokeStyle::setPaintOrderButtons(Gtk::ToggleButton *active) +{ + paintOrderFSM->set_active(active == paintOrderFSM); + paintOrderSFM->set_active(active == paintOrderSFM); + paintOrderFMS->set_active(active == paintOrderFMS); + paintOrderMFS->set_active(active == paintOrderMFS); + paintOrderSMF->set_active(active == paintOrderSMF); + paintOrderMSF->set_active(active == paintOrderMSF); +} + + +/** * Updates the marker combobox to highlight the appropriate marker and scroll to * that marker. */ diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h index 2605e1acf..d83067a4a 100644 --- a/src/widgets/stroke-style.h +++ b/src/widgets/stroke-style.h @@ -127,7 +127,8 @@ private: /** List of valid types for the stroke-style radio-button widget */ enum StrokeStyleButtonType { STROKE_STYLE_BUTTON_JOIN, ///< A button to set the line-join style - STROKE_STYLE_BUTTON_CAP ///< A button to set the line-cap style + STROKE_STYLE_BUTTON_CAP, ///< A button to set the line-cap style + STROKE_STYLE_BUTTON_ORDER ///< A button to set the paint-order style }; /** @@ -158,8 +159,10 @@ private: void setDashSelectorFromStyle(SPDashSelector *dsel, SPStyle *style); void setJoinType (unsigned const jointype); void setCapType (unsigned const captype); + void setPaintOrder (gchar const *paint_order); void setJoinButtons(Gtk::ToggleButton *active); void setCapButtons(Gtk::ToggleButton *active); + void setPaintOrderButtons(Gtk::ToggleButton *active); void scaleLine(); void setScaledDash(SPCSSAttr *css, int ndash, double *dash, double offset, double scale); void setMarkerColor(SPObject *marker, int loc, SPItem *item); @@ -204,6 +207,12 @@ private: StrokeStyleButton *capButt; StrokeStyleButton *capRound; StrokeStyleButton *capSquare; + StrokeStyleButton *paintOrderFSM; + StrokeStyleButton *paintOrderSFM; + StrokeStyleButton *paintOrderFMS; + StrokeStyleButton *paintOrderMFS; + StrokeStyleButton *paintOrderSMF; + StrokeStyleButton *paintOrderMSF; SPDashSelector *dashSelector; gboolean update; diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index 6f2807255..b9cce1d19 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -37,10 +37,11 @@ SwatchSelector::SwatchSelector() : color_selector->show(); pack_start(*color_selector); - _selected_color.signal_grabbed.connect(sigc::mem_fun(this, &SwatchSelector::_grabbedCb)); - _selected_color.signal_dragged.connect(sigc::mem_fun(this, &SwatchSelector::_draggedCb)); - _selected_color.signal_released.connect(sigc::mem_fun(this, &SwatchSelector::_releasedCb)); - _selected_color.signal_changed.connect(sigc::mem_fun(this, &SwatchSelector::_changedCb)); + //_selected_color.signal_grabbed.connect(sigc::mem_fun(this, &SwatchSelector::_grabbedCb)); + _selected_color.signal_dragged.connect(sigc::mem_fun(this, &SwatchSelector::_changedCb)); + _selected_color.signal_released.connect(sigc::mem_fun(this, &SwatchSelector::_changedCb)); + // signal_changed doesn't get called if updating shape with colour. + //_selected_color.signal_changed.connect(sigc::mem_fun(this, &SwatchSelector::_changedCb)); } SwatchSelector::~SwatchSelector() @@ -53,45 +54,6 @@ SPGradientSelector *SwatchSelector::getGradientSelector() return _gsel; } -void SwatchSelector::_grabbedCb() -{ -} - -void SwatchSelector::_draggedCb() -{ - // if (data) { - //SwatchSelector *swsel = reinterpret_cast<SwatchSelector*>(data); - - // TODO might have to block cycles - - // Copied from gradient-vector.cpp, but does not appear to cause visible changes: - /* - if (swsel->_gsel) { - SPGradient *gradient = swsel->_gsel->getVector(); - SPGradient *ngr = sp_gradient_ensure_vector_normalized(gradient); - if (ngr != gradient) { - // Our master gradient has changed - // TODO replace with proper - sp_gradient_vector_widget_load_gradient(GTK_WIDGET(swsel->_gsel), ngr); - } - - sp_gradient_ensure_vector(ngr); - - - SPStop* stop = ngr->getFirstStop(); - if (stop) { - swsel->_csel->base->getColorAlpha(stop->specified_color, &stop->opacity); - stop->currentColor = false; - // TODO push refresh - } - } - */ - // } -} - -void SwatchSelector::_releasedCb() -{ -} - void SwatchSelector::_changedCb() { if (_updating_color) { diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 5ca92b4c0..23acb74af 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -54,12 +54,18 @@ #include "ui/icon-names.h" #include "ui/tools/text-tool.h" #include "ui/tools/tool-base.h" +#include "ui/widget/unit-tracker.h" +#include "util/units.h" #include "verbs.h" #include "xml/repr.h" using Inkscape::DocumentUndo; using Inkscape::UI::ToolboxFactory; using Inkscape::UI::PrefPusher; +using Inkscape::Util::Unit; +using Inkscape::Util::Quantity; +using Inkscape::Util::unit_table; +using Inkscape::UI::Widget::UnitTracker; //#define DEBUG_TEXT @@ -502,6 +508,10 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } +static bool is_relative( Unit const *unit ) { + return (unit->abbr == "" || unit->abbr == "em" || unit->abbr == "ex" || unit->abbr == "%"); +} + static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) { // quit if run by the _changed callbacks @@ -510,25 +520,49 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); - // At the moment this handles only numerical values (i.e. no percent). + + // Get user selected unit and save as preference + UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker")); + Unit const *unit = tracker->getActiveUnit(); + g_return_if_fail(unit != NULL); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + + // Only save if not relative unit + if ( !is_relative(unit) ) { + // This nonsense is to get SP_CSS_UNIT_xx value corresponding to unit so + // we can save it (allows us to adjust line height value when unit changes). + SPILength temp_length; + Inkscape::CSSOStringStream temp_stream; + temp_stream << 1 << unit->abbr; + temp_length.read(temp_stream.str().c_str()); + prefs->setInt("/tools/text/lineheight/display_unit", temp_length.unit); + g_object_set_data( tbl, "lineheight_unit", GINT_TO_POINTER(temp_length.unit)); + } + // Set css line height. SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream osfs; - osfs << gtk_adjustment_get_value(adj)*100 << "%"; + if ( is_relative(unit) ) { + osfs << gtk_adjustment_get_value(adj) << unit->abbr; + } else { + // Inside SVG file, always use "px" for absolute units. + osfs << Quantity::convert(gtk_adjustment_get_value(adj), unit, "px") << "px"; + } sp_repr_css_set_property (css, "line-height", osfs.str().c_str()); + // Apply line-height to selected objects. SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, false); - // Until deprecated sodipodi:linespacing purged: + // Only need to save for undo if a text item has been changed. Inkscape::Selection *selection = desktop->getSelection(); bool modmade = false; std::vector<SPItem*> itemlist=selection->itemList(); for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end(); ++i){ if (SP_IS_TEXT (*i)) { - (*i)->getRepr()->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL)); modmade = true; } } @@ -554,6 +588,162 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } + +static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl ) +{ + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { + return; + } + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + + // Get old saved unit + int old_unit = GPOINTER_TO_INT( g_object_get_data(tbl, "lineheight_unit")); + + // Get user selected unit and save as preference + UnitTracker *tracker = reinterpret_cast<UnitTracker*>(g_object_get_data(tbl, "tracker")); + Unit const *unit = tracker->getActiveUnit(); + g_return_if_fail(unit != NULL); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + // Only save if not relative unit + if ( !is_relative(unit) ) { + // This nonsense is to get SP_CSS_UNIT_xx value corresponding to unit. + SPILength temp_length; + Inkscape::CSSOStringStream temp_stream; + temp_stream << 1 << unit->abbr; + temp_length.read(temp_stream.str().c_str()); + prefs->setInt("/tools/text/lineheight/display_unit", temp_length.unit); + g_object_set_data( tbl, "lineheight_unit", GINT_TO_POINTER(temp_length.unit)); + } + + // Read current line height value + EgeAdjustmentAction *line_height_act = + reinterpret_cast<EgeAdjustmentAction *>(g_object_get_data(tbl, "TextLineHeightAction")); + GtkAdjustment *line_height_adj = ege_adjustment_action_get_adjustment( line_height_act ); + double line_height = gtk_adjustment_get_value(line_height_adj); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Inkscape::Selection *selection = desktop->getSelection(); + std::vector<SPItem*> itemlist=selection->itemList(); + + // Convert between units + if ((unit->abbr == "" || unit->abbr == "em") && old_unit == SP_CSS_UNIT_EX) { + line_height *= 0.5; + } else if ((unit->abbr) == "ex" && (old_unit == SP_CSS_UNIT_EM || old_unit == SP_CSS_UNIT_NONE) ) { + line_height *= 2.0; + } else if ((unit->abbr == "" || unit->abbr == "em") && old_unit == SP_CSS_UNIT_PERCENT) { + line_height /= 100.0; + } else if ((unit->abbr) == "%" && (old_unit == SP_CSS_UNIT_EM || old_unit == SP_CSS_UNIT_NONE) ) { + line_height *= 100; + } else if ((unit->abbr) == "ex" && old_unit == SP_CSS_UNIT_PERCENT) { + line_height /= 50.0; + } else if ((unit->abbr) == "%" && old_unit == SP_CSS_UNIT_EX) { + line_height *= 50; + } else if (is_relative(unit)) { + // Convert absolute to relative... for the moment use average font-size + double font_size = 0; + int count = 0; + for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end(); ++i){ + if (SP_IS_TEXT (*i)) { + double doc_scale = Geom::Affine((*i)->i2dt_affine()).descrim(); + font_size += (*i)->style->font_size.computed * doc_scale; + ++count; + } + } + if (count > 0) { + font_size /= count; + } else { + font_size = 20; + } + + if (old_unit == SP_CSS_UNIT_NONE) old_unit = SP_CSS_UNIT_EM; + line_height = Quantity::convert(line_height, sp_style_get_css_unit_string(old_unit), "px"); + + if (font_size > 0) { + line_height /= font_size; + } + if ((unit->abbr) == "%") { + line_height *= 100; + } else if ((unit->abbr) == "ex") { + line_height *= 2; + } + } else if (old_unit==SP_CSS_UNIT_NONE || old_unit==SP_CSS_UNIT_PERCENT || + old_unit==SP_CSS_UNIT_EM || old_unit==SP_CSS_UNIT_EX) { + // Convert relative to absolute... for the moment use average font-size + double font_size = 0; + int count = 0; + for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end(); ++i){ + if (SP_IS_TEXT (*i)) { + double doc_scale = Geom::Affine((*i)->i2dt_affine()).descrim(); + font_size += (*i)->style->font_size.computed * doc_scale; + ++count; + } + } + if (count > 0) { + font_size /= count; + } else { + font_size = 20; + } + + if (old_unit == SP_CSS_UNIT_PERCENT) { + line_height /= 100.0; + } else if (old_unit == SP_CSS_UNIT_EX) { + line_height /= 2.0; + } + line_height *= font_size; + line_height = Quantity::convert(line_height, "px", unit); + } else { + // Convert between different absolute units (only used in GUI) + line_height = Quantity::convert(line_height, sp_style_get_css_unit_string(old_unit), unit); + } + + // Set css line height. + SPCSSAttr *css = sp_repr_css_attr_new (); + Inkscape::CSSOStringStream osfs; + if ( is_relative(unit) ) { + osfs << line_height << unit->abbr; + } else { + osfs << Quantity::convert(line_height, unit, "px") << "px"; + } + sp_repr_css_set_property (css, "line-height", osfs.str().c_str()); + + // Update GUI with line_height value. + gtk_adjustment_set_value(line_height_adj, line_height); + + // Apply line-height to selected objects. + sp_desktop_set_style (desktop, css, true, false); + + // Only need to save for undo if a text item has been changed. + bool modmade = false; + for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end(); ++i){ + if (SP_IS_TEXT (*i)) { + modmade = true; + } + } + + // Save for undo + if(modmade) { + DocumentUndo::maybeDone(SP_ACTIVE_DESKTOP->getDocument(), "ttb:line-height", SP_VERB_NONE, + _("Text: Change line-height unit")); + } + + // If no selected objects, set default. + SPStyle query(SP_ACTIVE_DOCUMENT); + int result_numbers = + sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + if (result_numbers == QUERY_STYLE_NOTHING) + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->mergeStyle("/tools/text/style", css); + } + + sp_repr_css_attr_unref (css); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + + static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl ) { // quit if run by the _changed callbacks @@ -1064,6 +1254,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ { activeButton = 3; } else { + // This should take 'direction' into account if (query.text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) activeButton = 0; if (query.text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) activeButton = 1; if (query.text_anchor.computed == SP_CSS_TEXT_ANCHOR_END) activeButton = 2; @@ -1071,16 +1262,46 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ ege_select_one_action_set_active( textAlignAction, activeButton ); - // Line height (spacing) + // Line height (spacing) and line height unit double height; + int line_height_unit = -1; if (query.line_height.normal) { height = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL; + line_height_unit = SP_CSS_UNIT_NONE; } else { - if (query.line_height.unit == SP_CSS_UNIT_PERCENT) { - height = query.line_height.value; - } else { - height = query.line_height.computed; - } + height = query.line_height.value; + line_height_unit = query.line_height.unit; + } + + switch (line_height_unit) { + case SP_CSS_UNIT_NONE: + case SP_CSS_UNIT_EM: + case SP_CSS_UNIT_EX: + break; + case SP_CSS_UNIT_PERCENT: + height *= 100.0; // Inkscape store % as fraction in .value + break; + case SP_CSS_UNIT_PX: + // If unit is set to 'px', use the preferred display unit (if absolute). + line_height_unit = + prefs->getInt("/tools/text/lineheight/display_unit", SP_CSS_UNIT_PT); + // But not if prefered unit is relative + if (line_height_unit != SP_CSS_UNIT_NONE && + line_height_unit != SP_CSS_UNIT_EM && + line_height_unit != SP_CSS_UNIT_EX && + line_height_unit != SP_CSS_UNIT_PERCENT) { + height = + Quantity::convert(height, "px", sp_style_get_css_unit_string(line_height_unit)); + } else { + line_height_unit = SP_CSS_UNIT_PX; + } + break; + default: + // If unit has been set by an external program to something other than 'px', use + // that unit. But height is average of computed values (px) so we need to convert + // back. + height = + Quantity::convert(height, "px", sp_style_get_css_unit_string(line_height_unit)); } GtkAction* lineHeightAction = GTK_ACTION( g_object_get_data( tbl, "TextLineHeightAction" ) ); @@ -1088,7 +1309,17 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( lineHeightAction )); gtk_adjustment_set_value( lineHeightAdjustment, height ); - + UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) ); + if( line_height_unit == SP_CSS_UNIT_NONE ) { + // Function 'sp_style_get_css_unit_string' returns 'px' for unit none. + // We need to avoid this. + tracker->setActiveUnitByAbbr(""); + } else { + tracker->setActiveUnitByAbbr(sp_style_get_css_unit_string(line_height_unit)); + } + // Save unit so we can do convertions between new/old units. + g_object_set_data( tbl, "lineheight_unit", GINT_TO_POINTER(line_height_unit)); + // Word spacing double wordSpacing; if (query.word_spacing.normal) wordSpacing = 0.0; @@ -1231,7 +1462,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ #endif g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); - } static void sp_text_toolbox_selection_modified(Inkscape::Selection *selection, guint /*flags*/, GObject *tbl) @@ -1332,6 +1562,23 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje g_object_set_data( holder, "TextFontFamilyAction", act ); // Change style of drop-down from menu to list +#if GTK_CHECK_VERSION(3,0,0) + GtkCssProvider *css_provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(css_provider, + "#TextFontFamilyAction_combobox {\n" + " -GtkComboBox-appears-as-list: true;\n" + "}\n" + "combobox window.popup scrolledwindow treeview separator {\n" + " -GtkWidget-wide-separators: true;\n" + " -GtkWidget-separator-height: 6;\n" + "}\n", + -1, NULL); + + GdkScreen *screen = gdk_screen_get_default(); + gtk_style_context_add_provider_for_screen(screen, + GTK_STYLE_PROVIDER(css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); +#else gtk_rc_parse_string ( "style \"dropdown-as-list-style\"\n" "{\n" @@ -1344,6 +1591,7 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje " GtkWidget::separator-height = 6\n" "}\n" "widget \"*gtk-combobox-popup-window.GtkScrolledWindow.GtkTreeView\" style \"fontfamily-separator-style\""); +#endif } /* Font size */ @@ -1582,6 +1830,15 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_orientation_changed), holder ); } + /* Line height unit tracker */ + UnitTracker* tracker = new UnitTracker(Inkscape::Util::UNIT_TYPE_LINEAR); + tracker->prependUnit(unit_table.getUnit("")); // No unit + tracker->addUnit(unit_table.getUnit("%")); + tracker->addUnit(unit_table.getUnit("em")); + tracker->addUnit(unit_table.getUnit("ex")); + tracker->setActiveUnit(unit_table.getUnit("%")); + g_object_set_data( holder, "tracker", tracker ); + /* Line height */ { // Drop down menu @@ -1599,20 +1856,28 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje holder, /* dataKludge */ FALSE, /* set alt-x keyboard shortcut? */ NULL, /* altx_mark */ - 0.0, 10.0, 0.01, 0.10, /* lower, upper, step (arrow up/down), page up/down */ + 0.0, 1000.0, 1.0, 10.0, /* lower, upper, step (arrow up/down), page up/down */ labels, values, G_N_ELEMENTS(labels), /* drop down menu */ sp_text_lineheight_value_changed, /* callback */ - NULL, /* unit tracker */ + NULL, // tracker, /* unit tracker */ 0.1, /* step (used?) */ 2, /* digits to show */ 1.0 /* factor (multiplies default) */ ); + //tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); g_object_set_data( holder, "TextLineHeightAction", eact ); g_object_set( G_OBJECT(eact), "iconId", "text_line_spacing", NULL ); } + /* Line height units */ + { + GtkAction* act = tracker->createAction( "TextLineHeightUnitsAction", _("Units"), ("") ); + gtk_action_group_add_action( mainActions, act ); + g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_text_lineheight_unit_changed), holder ); + } + /* Word spacing */ { // Drop down menu diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 6787ef6cc..f7b5e585f 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -55,6 +55,7 @@ #include "ui/tools-switch.h" #include "../ui/icon-names.h" #include "../ui/widget/style-swatch.h" +#include "../ui/widget/unit-tracker.h" #include "../verbs.h" #include "../widgets/button.h" #include "../widgets/spinbutton-events.h" @@ -126,7 +127,8 @@ Inkscape::IconSize ToolboxFactory::prefToSize( Glib::ustring const &path, int ba static Inkscape::IconSize sizeChoices[] = { Inkscape::ICON_SIZE_LARGE_TOOLBAR, Inkscape::ICON_SIZE_SMALL_TOOLBAR, - Inkscape::ICON_SIZE_MENU + Inkscape::ICON_SIZE_MENU, + Inkscape::ICON_SIZE_DIALOG }; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int index = prefs->getIntLimited( path, base, 0, G_N_ELEMENTS(sizeChoices) ); @@ -497,6 +499,9 @@ static gchar const * ui_descr = " <toolitem action='EraserModeAction' />" " <separator />" " <toolitem action='EraserWidthAction' />" + " <toolitem action='EraserBreakAppart' />" + " <separator />" + " <toolitem action='EraserMassAction' />" " </toolbar>" " <toolbar name='TextToolbar'>" @@ -512,6 +517,7 @@ static gchar const * ui_descr = " <toolitem action='TextSubscriptAction' />" " <separator />" " <toolitem action='TextLineHeightAction' />" + " <toolitem action='TextLineHeightUnitsAction' />" " <toolitem action='TextLetterSpacingAction' />" " <toolitem action='TextWordSpacingAction' />" " <toolitem action='TextDxAction' />" @@ -993,6 +999,7 @@ static GtkWidget* toolboxNewCommon( GtkWidget* tb, BarId id, GtkPositionType /*h gtk_widget_set_sensitive(tb, FALSE); GtkWidget *hb = gtk_event_box_new(); // A simple, neutral container. + gtk_widget_set_name(hb, "ToolboxCommon"); gtk_container_add(GTK_CONTAINER(hb), tb); gtk_widget_show(GTK_WIDGET(tb)); @@ -1010,6 +1017,7 @@ GtkWidget *ToolboxFactory::createToolToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "ToolToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1022,6 +1030,7 @@ GtkWidget *ToolboxFactory::createAuxToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "AuxToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1038,6 +1047,7 @@ GtkWidget *ToolboxFactory::createCommandsToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "CommandsToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1050,6 +1060,7 @@ GtkWidget *ToolboxFactory::createSnapToolbox() { #if GTK_CHECK_VERSION(3,0,0) GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(tb, "SnapToolbox"); gtk_box_set_homogeneous(GTK_BOX(tb), FALSE); #else GtkWidget *tb = gtk_vbox_new(FALSE, 0); @@ -1119,6 +1130,10 @@ EgeAdjustmentAction * create_adjustment_action( gchar const *name, g_object_set_data( dataKludge, prefs->getEntry(path).getEntryName().data(), adj ); } + if (unit_tracker) { + unit_tracker->addAdjustment(adj); + } + // Using a cast just to make sure we pass in the right kind of function pointer g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL ); @@ -1396,6 +1411,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) // converted to GtkActions and UIManager GtkWidget* kludge = gtk_toolbar_new(); + gtk_widget_set_name( kludge, "Kludge" ); g_object_set_data( G_OBJECT(kludge), "dtw", desktop->canvas); g_object_set_data( G_OBJECT(kludge), "desktop", desktop); dataHolders[aux_toolboxes[i].type_name] = kludge; @@ -1408,7 +1424,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) } else { sub_toolbox = aux_toolboxes[i].create_func(desktop); } - + gtk_widget_set_name( sub_toolbox, "SubToolBox" ); gtk_size_group_add_widget( grouper, sub_toolbox ); gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox); @@ -1426,6 +1442,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) #if GTK_CHECK_VERSION(3,0,0) GtkWidget* holder = gtk_grid_new(); + gtk_widget_set_name( holder, "ToolbarHolder" ); gtk_grid_attach( GTK_GRID(holder), kludge, 2, 0, 1, 1); #else GtkWidget* holder = gtk_table_new( 1, 3, FALSE ); |
