diff options
| author | Moritz Eberl <moritz@semiodesk.com> | 2016-04-13 14:05:30 +0000 |
|---|---|---|
| committer | Moritz Eberl <moritz@semiodesk.com> | 2016-04-13 14:05:30 +0000 |
| commit | 3a1aa63dc5df1aaebe89226e484f49289cae5f7c (patch) | |
| tree | 4afa9d90d2650f27f0411bc52ef608dca5e5a88b /src | |
| parent | Merge (diff) | |
| parent | gimpcolorwheel: Fix deprecated gtk_widget_style_attach #Hackfest2016 (diff) | |
| download | inkscape-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.cpp | 305 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 11 | ||||
| -rw-r--r-- | src/ui/dialog/clonetiler.cpp | 24 | ||||
| -rw-r--r-- | src/ui/interface.cpp | 12 | ||||
| -rw-r--r-- | src/ui/widget/color-icc-selector.cpp | 13 | ||||
| -rw-r--r-- | src/ui/widget/color-notebook.cpp | 4 | ||||
| -rw-r--r-- | src/ui/widget/color-scales.cpp | 6 | ||||
| -rw-r--r-- | src/ui/widget/gimpcolorwheel.c | 2 | ||||
| -rw-r--r-- | src/widgets/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/widgets/Makefile_insert | 6 | ||||
| -rw-r--r-- | src/widgets/desktop-widget.cpp | 53 | ||||
| -rw-r--r-- | src/widgets/ege-adjustment-action.cpp | 6 | ||||
| -rw-r--r-- | src/widgets/ege-select-one-action.cpp | 13 | ||||
| -rw-r--r-- | src/widgets/gradient-vector.cpp | 6 | ||||
| -rw-r--r-- | src/widgets/image-menu-item.c | 1071 | ||||
| -rw-r--r-- | src/widgets/image-menu-item.h | 81 | ||||
| -rw-r--r-- | src/widgets/ink-action.cpp | 42 | ||||
| -rw-r--r-- | src/widgets/ink-comboboxentry-action.cpp | 18 | ||||
| -rw-r--r-- | src/widgets/spw-utilities.cpp | 43 | ||||
| -rw-r--r-- | src/widgets/text-toolbar.cpp | 79 |
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), "×"); +#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), "×"); +#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 ); |
