summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorRichard White <rwhite8282@gmail.com>2016-05-19 01:17:29 +0000
committerRichard White <rwhite8282@gmail.com>2016-05-19 01:17:29 +0000
commit1fe9c2603c33fddcd9f2688b30e843f91e1a86fa (patch)
tree13289cbe033a46a40eb829437e115b5393e2ca84 /src/widgets
parentCorrected frame extension stroke and fill values on 64 bit machine. (diff)
parentGTK3: Another widget named. (diff)
downloadinkscape-1fe9c2603c33fddcd9f2688b30e843f91e1a86fa.tar.gz
inkscape-1fe9c2603c33fddcd9f2688b30e843f91e1a86fa.zip
Merge from Inkscape trunk.
(bzr r14668.1.3)
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/CMakeLists.txt10
-rw-r--r--src/widgets/Makefile_insert8
-rw-r--r--src/widgets/button.cpp24
-rw-r--r--src/widgets/desktop-widget.cpp186
-rw-r--r--src/widgets/eek-preview.cpp34
-rw-r--r--src/widgets/ege-adjustment-action.cpp6
-rw-r--r--src/widgets/ege-select-one-action.cpp13
-rw-r--r--src/widgets/eraser-toolbar.cpp82
-rw-r--r--src/widgets/font-selector.cpp17
-rw-r--r--src/widgets/gradient-vector.cpp6
-rw-r--r--src/widgets/icon.cpp46
-rw-r--r--src/widgets/image-menu-item.c1071
-rw-r--r--src/widgets/image-menu-item.h81
-rw-r--r--src/widgets/ink-action.cpp42
-rw-r--r--src/widgets/ink-comboboxentry-action.cpp18
-rw-r--r--src/widgets/ruler.cpp376
-rw-r--r--src/widgets/select-toolbar.cpp160
-rw-r--r--src/widgets/shrink-wrap-button.cpp65
-rw-r--r--src/widgets/shrink-wrap-button.h35
-rw-r--r--src/widgets/spw-utilities.cpp43
-rw-r--r--src/widgets/stroke-style.cpp219
-rw-r--r--src/widgets/stroke-style.h11
-rw-r--r--src/widgets/swatch-selector.cpp48
-rw-r--r--src/widgets/text-toolbar.cpp293
-rw-r--r--src/widgets/toolbox.cpp21
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 );