summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMoritz Eberl <moritz@semiodesk.com>2016-04-13 14:05:30 +0000
committerMoritz Eberl <moritz@semiodesk.com>2016-04-13 14:05:30 +0000
commit3a1aa63dc5df1aaebe89226e484f49289cae5f7c (patch)
tree4afa9d90d2650f27f0411bc52ef608dca5e5a88b /src
parentMerge (diff)
parentgimpcolorwheel: Fix deprecated gtk_widget_style_attach #Hackfest2016 (diff)
downloadinkscape-3a1aa63dc5df1aaebe89226e484f49289cae5f7c.tar.gz
inkscape-3a1aa63dc5df1aaebe89226e484f49289cae5f7c.zip
Merge and fixed CMake build
(bzr r14761.1.5)
Diffstat (limited to 'src')
-rw-r--r--src/display/sp-canvas.cpp305
-rw-r--r--src/display/sp-canvas.h11
-rw-r--r--src/ui/dialog/clonetiler.cpp24
-rw-r--r--src/ui/interface.cpp12
-rw-r--r--src/ui/widget/color-icc-selector.cpp13
-rw-r--r--src/ui/widget/color-notebook.cpp4
-rw-r--r--src/ui/widget/color-scales.cpp6
-rw-r--r--src/ui/widget/gimpcolorwheel.c2
-rw-r--r--src/widgets/CMakeLists.txt8
-rw-r--r--src/widgets/Makefile_insert6
-rw-r--r--src/widgets/desktop-widget.cpp53
-rw-r--r--src/widgets/ege-adjustment-action.cpp6
-rw-r--r--src/widgets/ege-select-one-action.cpp13
-rw-r--r--src/widgets/gradient-vector.cpp6
-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/spw-utilities.cpp43
-rw-r--r--src/widgets/text-toolbar.cpp79
20 files changed, 1561 insertions, 242 deletions
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index df84e379c..644da8d5a 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -8,9 +8,11 @@
* fred
* bbyak
* Jon A. Cruz <jon@joncruz.org>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
* Copyright (C) 1998 The Free Software Foundation
* Copyright (C) 2002-2006 authors
+ * Copyright (C) 2016 Google Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -122,7 +124,7 @@ struct SPCanvasClass {
namespace {
-gint const UPDATE_PRIORITY = G_PRIORITY_HIGH_IDLE;
+gint const UPDATE_PRIORITY = G_PRIORITY_DEFAULT_IDLE;
GdkWindow *getWindow(SPCanvas *canvas)
{
@@ -935,7 +937,6 @@ void sp_canvas_class_init(SPCanvasClass *klass)
static void sp_canvas_init(SPCanvas *canvas)
{
gtk_widget_set_has_window (GTK_WIDGET (canvas), TRUE);
- gtk_widget_set_double_buffered (GTK_WIDGET (canvas), FALSE);
gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE);
canvas->_pick_event.type = GDK_LEAVE_NOTIFY;
@@ -956,9 +957,8 @@ static void sp_canvas_init(SPCanvas *canvas)
canvas->_drawing_disabled = false;
- canvas->_tiles=NULL;
- canvas->_tLeft=canvas->_tTop=canvas->_tRight=canvas->_tBottom=0;
- canvas->_tile_h=canvas->_tile_h=0;
+ canvas->_backing_store = NULL;
+ canvas->_clean_region = cairo_region_create();
canvas->_forced_redraw_count = 0;
canvas->_forced_redraw_limit = -1;
@@ -967,22 +967,15 @@ static void sp_canvas_init(SPCanvas *canvas)
canvas->_enable_cms_display_adj = false;
new (&canvas->_cms_key) Glib::ustring("");
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
-
- canvas->_is_scrolling = false;
}
void SPCanvas::shutdownTransients()
{
- // We turn off the need_redraw flag, since if the canvas is mapped again
- // it will request a redraw anyways. We do not turn off the need_update
- // flag, though, because updates are not queued when the canvas remaps
- // itself.
- //
- _need_redraw = FALSE;
- if (_tiles) g_free(_tiles);
- _tiles = NULL;
- _tLeft = _tTop = _tRight = _tBottom = 0;
- _tile_h = _tile_h = 0;
+ // Reset the clean region
+ if (_clean_region && !cairo_region_is_empty(_clean_region)) {
+ cairo_region_destroy(_clean_region);
+ _clean_region = cairo_region_create();
+ }
if (_grabbed_item) {
_grabbed_item = NULL;
@@ -1005,6 +998,14 @@ void SPCanvas::dispose(GObject *object)
g_object_unref (canvas->_root);
canvas->_root = NULL;
}
+ if (canvas->_backing_store) {
+ cairo_surface_destroy(canvas->_backing_store);
+ canvas->_backing_store = NULL;
+ }
+ if (canvas->_clean_region) {
+ cairo_region_destroy(canvas->_clean_region);
+ canvas->_clean_region = NULL;
+ }
canvas->shutdownTransients();
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
@@ -1138,41 +1139,41 @@ void SPCanvas::handle_size_request(GtkWidget *widget, GtkRequisition *req)
void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
{
SPCanvas *canvas = SP_CANVAS (widget);
- GtkAllocation widg_allocation;
+ GtkAllocation old_allocation;
- gtk_widget_get_allocation (widget, &widg_allocation);
+ gtk_widget_get_allocation(widget, &old_allocation);
-// Geom::IntRect old_area = Geom::IntRect::from_xywh(canvas->x0, canvas->y0,
-// widg_allocation.width, widg_allocation.height);
+// Geom::IntRect old_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0,
+// old_allocation.width, old_allocation.height);
Geom::IntRect new_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0,
allocation->width, allocation->height);
- // Schedule redraw of new region
- canvas->resizeTiles(canvas->_x0, canvas->_y0, canvas->_x0 + allocation->width, canvas->_y0 + allocation->height);
- if (SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed)
- SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed (canvas->_root, new_area);
-
- if (allocation->width > widg_allocation.width) {
- canvas->requestRedraw(canvas->_x0 + widg_allocation.width,
- 0,
- canvas->_x0 + allocation->width,
- canvas->_y0 + allocation->height);
- }
- if (allocation->height > widg_allocation.height) {
- canvas->requestRedraw(0,
- canvas->_y0 + widg_allocation.height,
- canvas->_x0 + allocation->width,
- canvas->_y0 + allocation->height);
+ // resize backing store; the clean region does not change
+ cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ allocation->width, allocation->height);
+ if (canvas->_backing_store) {
+ cairo_t *cr = cairo_create(new_backing_store);
+ cairo_set_source_surface(cr, canvas->_backing_store, 0, 0);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+ cairo_surface_destroy(canvas->_backing_store);
}
+ canvas->_backing_store = new_backing_store;
gtk_widget_set_allocation (widget, allocation);
+ // Schedule redraw of new region
+ if (SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed)
+ SP_CANVAS_ITEM_GET_CLASS (canvas->_root)->viewbox_changed (canvas->_root, new_area);
+
if (gtk_widget_get_realized (widget)) {
gdk_window_move_resize (gtk_widget_get_window (widget),
allocation->x, allocation->y,
allocation->width, allocation->height);
}
+ canvas->addIdle();
}
int SPCanvas::emitEvent(GdkEvent *event)
@@ -1554,11 +1555,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect
#if GTK_CHECK_VERSION(3,0,0)
GtkStyleContext *context = gtk_widget_get_style_context(widget);
- GdkRGBA color;
- gtk_style_context_get_background_color(context,
- gtk_widget_get_state_flags(widget),
- &color);
- gdk_cairo_set_source_rgba(buf.ct, &color);
+ gtk_render_background(context, buf.ct, 0, 0, paint_rect.width(), paint_rect.height());
#else
GtkStyle *style = gtk_widget_get_style (widget);
gdk_cairo_set_source_color(buf.ct, &style->bg[GTK_STATE_NORMAL]);
@@ -1600,7 +1597,8 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect
}
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
- cairo_t *xct = gdk_cairo_create(gtk_widget_get_window (widget));
+ //cairo_t *xct = gdk_cairo_create(gtk_widget_get_window (widget));
+ cairo_t *xct = cairo_create(_backing_store);
cairo_translate(xct, paint_rect.left() - _x0, paint_rect.top() - _y0);
cairo_rectangle(xct, 0, 0, paint_rect.width(), paint_rect.height());
cairo_clip(xct);
@@ -1609,6 +1607,12 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect
cairo_paint(xct);
cairo_destroy(xct);
cairo_surface_destroy(imgs);
+
+ cairo_rectangle_int_t crect = { paint_rect.left(), paint_rect.right(), paint_rect.width(), paint_rect.height() };
+ cairo_region_union_rectangle(_clean_region, &crect);
+
+ gtk_widget_queue_draw_area(GTK_WIDGET(this), paint_rect.left() -_x0, paint_rect.top() - _y0,
+ paint_rect.width(), paint_rect.height());
}
struct PaintRectSetup {
@@ -1792,52 +1796,63 @@ void SPCanvas::endForcedFullRedraws()
_forced_redraw_limit = -1;
}
-#if GTK_CHECK_VERSION(3,0,0)
gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) {
SPCanvas *canvas = SP_CANVAS(widget);
cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr);
+ cairo_region_t *draw_region = cairo_region_create();
for (int i = 0; i < rects->num_rectangles; i++) {
cairo_rectangle_t rectangle = rects->rectangles[i];
+ Geom::Rect dr = Geom::Rect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0,
+ rectangle.width, rectangle.height);
+ Geom::IntRect ir = dr.roundOutwards();
+ cairo_rectangle_int_t irect = { ir.left(), ir.top(), ir.width(), ir.height() };
+ cairo_region_union_rectangle(draw_region, &irect);
+ }
+ cairo_rectangle_list_destroy(rects);
- Geom::IntRect r = Geom::IntRect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0,
- rectangle.width, rectangle.height);
-
- canvas->requestRedraw(r.left(), r.top(), r.right(), r.bottom());
+ cairo_region_t *draw_dirty = cairo_region_copy(draw_region);
+ cairo_region_subtract(draw_dirty, canvas->_clean_region);
+ cairo_region_intersect(draw_region, canvas->_clean_region);
+
+ // Draw the clean portion
+ if (!cairo_region_is_empty(draw_region)) {
+ cairo_region_translate(draw_region, -canvas->_x0, -canvas->_y0);
+ cairo_save(cr);
+ int n_rects = cairo_region_num_rectangles(draw_region);
+ for (int i = 0; i < n_rects; ++i) {
+ cairo_rectangle_int_t crect;
+ cairo_region_get_rectangle(draw_region, i, &crect);
+ cairo_rectangle(cr, crect.x, crect.y, crect.width, crect.height);
+ }
+ cairo_clip(cr);
+ cairo_set_source_surface(cr, canvas->_backing_store, 0, 0);
+ cairo_paint(cr);
+ cairo_restore(cr);
}
- cairo_rectangle_list_destroy(rects);
+ // Render the dirty portion in the background
+ if (!cairo_region_is_empty(draw_dirty)) {
+ canvas->addIdle();
+ }
+ cairo_region_destroy(draw_region);
+ cairo_region_destroy(draw_dirty);
- return FALSE;
+ return TRUE;
}
-#else
+#if !GTK_CHECK_VERSION(3,0,0)
gboolean SPCanvas::handle_expose(GtkWidget *widget, GdkEventExpose *event)
{
- SPCanvas *canvas = SP_CANVAS(widget);
+ cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
- if (!gtk_widget_is_drawable (widget) ||
- (event->window != getWindow(canvas))) {
- return FALSE;
- }
-
- int n_rects = 0;
- GdkRectangle *rects = NULL;
- gdk_region_get_rectangles(event->region, &rects, &n_rects);
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
+ gboolean result = SPCanvas::handle_draw(widget, cr);
- if(rects == NULL)
- return FALSE;
-
- for (int i = 0; i < n_rects; i++) {
- GdkRectangle rectangle = rects[i];
+ cairo_destroy (cr);
- Geom::IntRect r = Geom::IntRect::from_xywh(rectangle.x + canvas->_x0, rectangle.y + canvas->_y0,
- rectangle.width, rectangle.height);
-
- canvas->requestRedraw(r.left(), r.top(), r.right(), r.bottom());
- }
-
- return FALSE;
+ return result;
}
#endif
@@ -1890,42 +1905,22 @@ int SPCanvas::paint()
_need_update = FALSE;
}
- if (!_need_redraw) {
- return TRUE;
- }
-
- Cairo::RefPtr<Cairo::Region> to_paint = Cairo::Region::create();
-
- for (int j = _tTop; j < _tBottom; ++j) {
- for (int i = _tLeft; i < _tRight; ++i) {
- int tile_index = (i - _tLeft) + (j - _tTop) * _tile_h;
-
- if (_tiles[tile_index]) { // if this tile is dirtied (nonzero)
- Cairo::RectangleInt rect = {i*TILE_SIZE, j*TILE_SIZE,
- TILE_SIZE, TILE_SIZE};
- to_paint->do_union(rect);
- }
- }
- }
-
- int n_rect = to_paint->get_num_rectangles();
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(GTK_WIDGET(this), &allocation);
+ cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height };
+ cairo_region_t *to_draw = cairo_region_create_rectangle(&crect);
+ cairo_region_subtract(to_draw, _clean_region);
- if (n_rect > 0) {
- for (int i=0; i < n_rect; i++) {
- Cairo::RectangleInt rect = to_paint->get_rectangle(i);
- int x0 = rect.x;
- int y0 = rect.y;
- int x1 = x0 + rect.width;
- int y1 = y0 + rect.height;
- if (!paintRect(x0, y0, x1, y1)) {
- // Aborted
- return FALSE;
- };
- }
+ int n_rects = cairo_region_num_rectangles(to_draw);
+ for (int i = 0; i < n_rects; ++i) {
+ cairo_rectangle_int_t crect;
+ cairo_region_get_rectangle(to_draw, i, &crect);
+ if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) {
+ // Aborted
+ return FALSE;
+ };
}
- _need_redraw = FALSE;
-
// we've had a full unaborted redraw, reset the full redraw counter
if (_forced_redraw_limit != -1) {
_forced_redraw_count = 0;
@@ -2012,7 +2007,27 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll
gtk_widget_get_allocation(&_widget, &allocation);
- resizeTiles(_x0, _y0, _x0 + allocation.width, _y0 + allocation.height);
+ assert(_backing_store);
+ cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ allocation.width, allocation.height);
+ cairo_t *cr = cairo_create(new_backing_store);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cr);
+ cairo_set_source_surface(cr, _backing_store, -dx, -dy);
+ cairo_paint(cr);
+ cairo_destroy(cr);
+ cairo_surface_destroy(_backing_store);
+ _backing_store = new_backing_store;
+
+ if (clear) {
+ cairo_region_destroy(_clean_region);
+ _clean_region = cairo_region_create();
+ } else {
+ cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height };
+ cairo_region_intersect_rectangle(_clean_region, &crect);
+ }
+
if (SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed) {
SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed(_root, new_area);
}
@@ -2020,19 +2035,17 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll
if (!clear) {
// scrolling without zoom; redraw only the newly exposed areas
if ((dx != 0) || (dy != 0)) {
- this->_is_scrolling = is_scrolling;
if (gtk_widget_get_realized(GTK_WIDGET(this))) {
gdk_window_scroll(getWindow(this), -dx, -dy);
}
}
- } else {
- // scrolling as part of zoom; do nothing here - the next do_update will perform full redraw
}
+ addIdle();
}
void SPCanvas::updateNow()
{
- if (_need_update || _need_redraw) {
+ if (_need_update) {
doUpdate();
}
}
@@ -2045,26 +2058,16 @@ void SPCanvas::requestUpdate()
void SPCanvas::requestRedraw(int x0, int y0, int x1, int y1)
{
- GtkAllocation allocation;
-
if (!gtk_widget_is_drawable( GTK_WIDGET(this) )) {
return;
}
- if ((x0 >= x1) || (y0 >= y1)) {
+ if (x0 >= x1 || y0 >= y1) {
return;
}
Geom::IntRect bbox(x0, y0, x1, y1);
- gtk_widget_get_allocation(GTK_WIDGET(this), &allocation);
-
- Geom::IntRect canvas_rect = Geom::IntRect::from_xywh(this->_x0, this->_y0,
- allocation.width, allocation.height);
-
- Geom::OptIntRect clip = bbox & canvas_rect;
- if (clip) {
- dirtyRect(*clip);
- addIdle();
- }
+ dirtyRect(bbox);
+ addIdle();
}
/**
@@ -2168,63 +2171,17 @@ inline int sp_canvas_tile_ceil(int x)
return ((x + (TILE_SIZE - 1)) & (~(TILE_SIZE - 1))) / TILE_SIZE;
}
-void SPCanvas::resizeTiles(int nl, int nt, int nr, int nb)
-{
- if ( nl >= nr || nt >= nb ) {
- if (_tiles) g_free(_tiles);
- _tLeft = _tTop = _tRight = _tBottom = 0;
- _tile_h = _tile_h = 0;
- _tiles = NULL;
- return;
- }
- int tl = sp_canvas_tile_floor(nl);
- int tt = sp_canvas_tile_floor(nt);
- int tr = sp_canvas_tile_ceil(nr);
- int tb = sp_canvas_tile_ceil(nb);
-
- int nh = tr-tl, nv = tb-tt;
- uint8_t *ntiles = (uint8_t*) g_malloc(nh * nv * sizeof(uint8_t));
- for (int i = tl; i < tr; i++) {
- for (int j = tt; j < tb; j++) {
- int ind = (i-tl) + (j-tt)*nh;
- if ( i >= _tLeft && i < _tRight && j >= _tTop && j < _tBottom ) {
- ntiles[ind] = _tiles[(i - _tLeft) + (j - _tTop) * _tile_h]; // copy from the old tile
- } else {
- ntiles[ind] = 0; // newly exposed areas get 0
- }
- }
- }
- if (_tiles) g_free(_tiles);
- _tiles = ntiles;
- _tLeft = tl;
- _tTop = tt;
- _tRight = tr;
- _tBottom = tb;
- _tile_h = nh;
- _tile_h = nv;
-}
-
void SPCanvas::dirtyRect(Geom::IntRect const &area) {
- _need_redraw = TRUE;
markRect(area, 1);
}
void SPCanvas::markRect(Geom::IntRect const &area, uint8_t val)
{
- int tl = sp_canvas_tile_floor(area.left());
- int tt = sp_canvas_tile_floor(area.top());
- int tr = sp_canvas_tile_ceil(area.right());
- int tb = sp_canvas_tile_ceil(area.bottom());
- if ( tl >= _tRight || tr <= _tLeft || tt >= _tBottom || tb <= _tTop ) return;
- if ( tl < _tLeft ) tl = _tLeft;
- if ( tr > _tRight ) tr = _tRight;
- if ( tt < _tTop ) tt = _tTop;
- if ( tb > _tBottom ) tb = _tBottom;
-
- for (int i=tl; i<tr; i++) {
- for (int j=tt; j<tb; j++) {
- _tiles[(i - _tLeft) + (j - _tTop) * _tile_h] = val;
- }
+ cairo_rectangle_int_t crect = { area.left(), area.top(), area.width(), area.height() };
+ if (val) {
+ cairo_region_subtract_rectangle(_clean_region, &crect);
+ } else {
+ cairo_region_union_rectangle(_clean_region, &crect);
}
}
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 1a13250b3..a1f8d0a1a 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -11,9 +11,11 @@
* Raph Levien <raph@gimp.org>
* Lauris Kaplinski <lauris@kaplinski.com>
* Jon A. Cruz <jon@joncruz.org>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
*
* Copyright (C) 1998 The Free Software Foundation
* Copyright (C) 2002 Lauris Kaplinski
+ * Copyright (C) 2016 Google Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -155,9 +157,8 @@ public:
*/
static gint handle_scroll(GtkWidget *widget, GdkEventScroll *event);
static gint handle_motion(GtkWidget *widget, GdkEventMotion *event);
-#if GTK_CHECK_VERSION(3,0,0)
static gboolean handle_draw(GtkWidget *widget, cairo_t *cr);
-#else
+#if !GTK_CHECK_VERSION(3,0,0)
static gboolean handle_expose(GtkWidget *widget, GdkEventExpose *event);
#endif
static gint handle_key_event(GtkWidget *widget, GdkEventKey *event);
@@ -180,9 +181,8 @@ public:
int _y0;
/* Area that needs redrawing, stored as a microtile array */
- int _tLeft, _tTop, _tRight, _tBottom;
- int _tile_w, _tile_h;
- uint8_t *_tiles;
+ cairo_surface_t *_backing_store;
+ cairo_region_t *_clean_region;
/** Last known modifier state, for deferred repick when a button is down. */
int _state;
@@ -208,7 +208,6 @@ public:
int _close_enough;
unsigned int _need_update : 1;
- unsigned int _need_redraw : 1;
unsigned int _need_repick : 1;
int _forced_redraw_count;
diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp
index fbd050f8e..9656878e0 100644
--- a/src/ui/dialog/clonetiler.cpp
+++ b/src/ui/dialog/clonetiler.cpp
@@ -1061,7 +1061,11 @@ CloneTiler::CloneTiler () :
{
GtkWidget *l = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(l), "&#215;");
+#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, TRUE, TRUE, 0);
}
@@ -1135,7 +1139,11 @@ CloneTiler::CloneTiler () :
{
GtkWidget *l = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(l), "&#215;");
+#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, TRUE, TRUE, 0);
}
@@ -2777,7 +2785,12 @@ GtkWidget * CloneTiler::clonetiler_spinbox(const char *tip, const char *attr, do
{
GtkWidget *l = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL(l), suffix);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(l, GTK_ALIGN_END);
+ gtk_widget_set_valign(l, GTK_ALIGN_START);
+#else
gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0);
+#endif
gtk_box_pack_start (GTK_BOX (hb), l, FALSE, FALSE, 0);
}
@@ -2853,14 +2866,13 @@ void CloneTiler::clonetiler_reset(GtkWidget */*widget*/, GtkWidget *dlg)
void CloneTiler::clonetiler_table_attach(GtkWidget *table, GtkWidget *widget, float align, int row, int col)
{
- GtkWidget *a = gtk_alignment_new (align, 0, 0, 0);
- gtk_container_add(GTK_CONTAINER(a), widget);
-
#if GTK_CHECK_VERSION(3,0,0)
- gtk_widget_set_halign(table, GTK_ALIGN_FILL);
- gtk_widget_set_valign(table, GTK_ALIGN_CENTER);
- gtk_grid_attach(GTK_GRID(table), a, col, row, 1, 1);
+ gtk_widget_set_halign(widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign(widget, GTK_ALIGN_START);
+ gtk_grid_attach(GTK_GRID(table), widget, col, row, 1, 1);
#else
+ GtkWidget *a = gtk_alignment_new (align, 0, 0, 0);
+ gtk_container_add(GTK_CONTAINER(a), widget);
gtk_table_attach ( GTK_TABLE (table), a, col, col + 1, row, row + 1, GTK_FILL, (GtkAttachOptions)0, 0, 0 );
#endif
}
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 8639861f8..a16bbc472 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -79,6 +79,10 @@
#include "message-stack.h"
#include "ui/dialog/layer-properties.h"
+#if GTK_CHECK_VERSION(3,0,0)
+ #include "widgets/image-menu-item.h"
+#endif
+
#include <gdk/gdkkeysyms.h>
#include <glibmm/miscutils.h>
@@ -413,7 +417,11 @@ sp_ui_menuitem_add_icon( GtkWidget *item, gchar *icon_name )
icon = sp_icon_new( Inkscape::ICON_SIZE_MENU, icon_name );
gtk_widget_show(icon);
+#if GTK_CHECK_VERSION(3,0,0)
+ image_menu_item_set_image((ImageMenuItem *) item, icon);
+#else
gtk_image_menu_item_set_image((GtkImageMenuItem *) item, icon);
+#endif
} // end of sp_ui_menu_add_icon
void
@@ -467,7 +475,11 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb
if (radio) {
item = gtk_radio_menu_item_new_with_mnemonic(group, action->name);
} else {
+#if GTK_CHECK_VERSION(3,0,0)
+ item = image_menu_item_new_with_mnemonic(action->name);
+#else
item = gtk_image_menu_item_new_with_mnemonic(action->name);
+#endif
}
gtk_label_set_markup_with_mnemonic( GTK_LABEL(gtk_bin_get_child(GTK_BIN (item))), action->name);
diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp
index 2fe4a0704..ec2e69fb3 100644
--- a/src/ui/widget/color-icc-selector.cpp
+++ b/src/ui/widget/color-icc-selector.cpp
@@ -377,7 +377,6 @@ void ColorICCSelector::init()
(gpointer)_impl);
gtk_widget_set_sensitive(_impl->_fixupBtn, FALSE);
gtk_widget_set_tooltip_text(_impl->_fixupBtn, _("Fix RGB fallback to match icc-color() value."));
- // gtk_misc_set_alignment( GTK_MISC (_impl->_fixupBtn), 1.0, 0.5 );
gtk_widget_show(_impl->_fixupBtn);
attachToGridOrTable(t, _impl->_fixupBtn, 0, row, 1, 1);
@@ -431,7 +430,13 @@ void ColorICCSelector::init()
#endif
_impl->_compUI[i]._label = gtk_label_new_with_mnemonic(labelStr.c_str());
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(_impl->_compUI[i]._label, GTK_ALIGN_END);
+#else
gtk_misc_set_alignment(GTK_MISC(_impl->_compUI[i]._label), 1.0, 0.5);
+#endif
+
gtk_widget_show(_impl->_compUI[i]._label);
gtk_widget_set_no_show_all(_impl->_compUI[i]._label, TRUE);
@@ -489,7 +494,13 @@ void ColorICCSelector::init()
// Label
_impl->_label = gtk_label_new_with_mnemonic(_("_A:"));
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(_impl->_label, GTK_ALIGN_END);
+#else
gtk_misc_set_alignment(GTK_MISC(_impl->_label), 1.0, 0.5);
+#endif
+
gtk_widget_show(_impl->_label);
attachToGridOrTable(t, _impl->_label, 0, row, 1, 1);
diff --git a/src/ui/widget/color-notebook.cpp b/src/ui/widget/color-notebook.cpp
index 60abf43bf..6d7ada734 100644
--- a/src/ui/widget/color-notebook.cpp
+++ b/src/ui/widget/color-notebook.cpp
@@ -210,7 +210,11 @@ void ColorNotebook::_initUI()
/* Create RGBA entry and color preview */
_rgbal = gtk_label_new_with_mnemonic(_("RGBA_:"));
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(_rgbal, GTK_ALIGN_END);
+#else
gtk_misc_set_alignment(GTK_MISC(_rgbal), 1.0, 0.5);
+#endif
gtk_box_pack_start(GTK_BOX(rgbabox), _rgbal, TRUE, TRUE, 2);
ColorEntry *rgba_entry = Gtk::manage(new ColorEntry(_selected_color));
diff --git a/src/ui/widget/color-scales.cpp b/src/ui/widget/color-scales.cpp
index 170f83887..48a2693bc 100644
--- a/src/ui/widget/color-scales.cpp
+++ b/src/ui/widget/color-scales.cpp
@@ -92,7 +92,13 @@ void ColorScales::_initUI(SPColorScalesMode mode)
for (i = 0; i < static_cast<gint>(G_N_ELEMENTS(_a)); i++) {
/* Label */
_l[i] = gtk_label_new("");
+
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(_l[i], GTK_ALIGN_END);
+#else
gtk_misc_set_alignment(GTK_MISC(_l[i]), 1.0, 0.5);
+#endif
+
gtk_widget_show(_l[i]);
#if GTK_CHECK_VERSION(3, 0, 0)
diff --git a/src/ui/widget/gimpcolorwheel.c b/src/ui/widget/gimpcolorwheel.c
index 3642848df..d54486505 100644
--- a/src/ui/widget/gimpcolorwheel.c
+++ b/src/ui/widget/gimpcolorwheel.c
@@ -303,7 +303,9 @@ gimp_color_wheel_realize (GtkWidget *widget)
priv->window = gdk_window_new (parent_window, &attr, attr_mask);
gdk_window_set_user_data (priv->window, wheel);
+#if !GTK_CHECK_VERSION(3,0,0)
gtk_widget_style_attach (widget);
+#endif
}
static void
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index c38bde5cf..8cb6e947f 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -110,6 +110,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 +126,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..2ee0f7002 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 \
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 3fa607820..759be551f 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -572,10 +572,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;
@@ -692,38 +700,37 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
gtk_container_add (GTK_CONTAINER (eventbox), dtw->coord_status);
gtk_widget_set_tooltip_text (eventbox, _("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:"));
#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);
@@ -756,7 +763,13 @@ void SPDesktopWidget::init( SPDesktopWidget *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);
+
+#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."));
@@ -1685,7 +1698,8 @@ 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 );
+ gtk_container_remove(GTK_CONTAINER(hbox), toolbox);
+ gtk_container_add(GTK_CONTAINER(vbox), toolbox);
gtk_box_set_child_packing(GTK_BOX(vbox), toolbox, FALSE, TRUE, 0, GTK_PACK_START);
}
ToolboxFactory::setOrientation(toolbox, GTK_ORIENTATION_HORIZONTAL);
@@ -1693,7 +1707,8 @@ 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 );
+ gtk_container_remove(GTK_CONTAINER(vbox), toolbox);
+ gtk_container_add(GTK_CONTAINER(hbox), 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 );
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/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/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/spw-utilities.cpp b/src/widgets/spw-utilities.cpp
index 7030753a5..89ab76585 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)
+ gtk_widget_set_margin_start(label_widget, 4);
+ gtk_widget_set_margin_end(label_widget, 4);
+#if GTK_CHECK_VERSION(3,12,0)
+#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/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index e71c911bd..661fc6fa9 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -508,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
@@ -524,21 +528,22 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl )
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- // 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));
-
+ // 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;
- // We should handle unitless values as well as 'em' and 'ex'
- if ((unit->abbr) == "em" || unit->abbr == "ex" || unit->abbr == "%") {
+ if ( is_relative(unit) ) {
osfs << gtk_adjustment_get_value(adj) << unit->abbr;
} else {
// Inside SVG file, always use "px" for absolute units.
@@ -601,13 +606,16 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl )
g_return_if_fail(unit != NULL);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- // 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));
+ // 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 =
@@ -620,19 +628,19 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl )
std::vector<SPItem*> itemlist=selection->itemList();
// Convert between units
- if ((unit->abbr) == "em" && old_unit == SP_CSS_UNIT_EX) {
+ 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) {
+ } 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) == "em" && old_unit == SP_CSS_UNIT_PERCENT) {
+ } 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) {
+ } 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 ((unit->abbr) == "%" || (unit->abbr) == "em" || (unit->abbr) == "ex") {
+ } else if (is_relative(unit)) {
// Convert absolute to relative... for the moment use average font-size
double font_size = 0;
int count = 0;
@@ -648,7 +656,10 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl )
} 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;
}
@@ -657,7 +668,8 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl )
} else if ((unit->abbr) == "ex") {
line_height *= 2;
}
- } else if (old_unit==SP_CSS_UNIT_PERCENT || old_unit==SP_CSS_UNIT_EM || old_unit==SP_CSS_UNIT_EX) {
+ } 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;
@@ -689,8 +701,7 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl )
// Set css line height.
SPCSSAttr *css = sp_repr_css_attr_new ();
Inkscape::CSSOStringStream osfs;
- // We should handle unitless values as well as 'em' and 'ex'
- if ((unit->abbr) == "em" || unit->abbr == "ex" || unit->abbr == "%") {
+ if ( is_relative(unit) ) {
osfs << line_height << unit->abbr;
} else {
osfs << Quantity::convert(line_height, unit, "px") << "px";
@@ -1264,8 +1275,6 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
switch (line_height_unit) {
case SP_CSS_UNIT_NONE:
- // tracker can't show no unit... use 'em'
- line_height_unit = SP_CSS_UNIT_EM;
case SP_CSS_UNIT_EM:
case SP_CSS_UNIT_EX:
break;
@@ -1276,7 +1285,9 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
// 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);
- if (line_height_unit != SP_CSS_UNIT_EM &&
+ // 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 =
@@ -1299,7 +1310,13 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/
gtk_adjustment_set_value( lineHeightAdjustment, height );
UnitTracker* tracker = reinterpret_cast<UnitTracker*>( g_object_get_data( tbl, "tracker" ) );
- tracker->setActiveUnitByAbbr(sp_style_get_css_unit_string(line_height_unit));
+ 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));
@@ -1797,10 +1814,10 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
/* 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->addUnit(unit_table.getUnit("None"));
tracker->setActiveUnit(unit_table.getUnit("%"));
g_object_set_data( holder, "tracker", tracker );