From 490f3d7181baff4d215d0077be9e4939f9af5fde Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 12 Apr 2016 16:23:42 +0100 Subject: Hackfest 2016: Fix SPCanvas to comply with GTK3 rendering model. For now, causes redraw issues with SVG preview in the open dialog. (bzr r14795) --- src/display/sp-canvas.cpp | 279 ++++++++++++++++++++++------------------------ src/display/sp-canvas.h | 8 +- 2 files changed, 139 insertions(+), 148 deletions(-) (limited to 'src') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index df84e379c..2dced2512 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -122,7 +122,7 @@ struct SPCanvasClass { namespace { -gint const UPDATE_PRIORITY = G_PRIORITY_HIGH_IDLE; +gint const UPDATE_PRIORITY = G_PRIORITY_DEFAULT_IDLE; GdkWindow *getWindow(SPCanvas *canvas) { @@ -956,9 +956,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->_dirty_region = cairo_region_create(); canvas->_forced_redraw_count = 0; canvas->_forced_redraw_limit = -1; @@ -967,8 +966,6 @@ 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() @@ -979,10 +976,6 @@ void SPCanvas::shutdownTransients() // itself. // _need_redraw = FALSE; - if (_tiles) g_free(_tiles); - _tiles = NULL; - _tLeft = _tTop = _tRight = _tBottom = 0; - _tile_h = _tile_h = 0; 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->_dirty_region) { + cairo_region_destroy(canvas->_dirty_region); + canvas->_dirty_region = NULL; + } canvas->shutdownTransients(); #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) @@ -1138,41 +1139,53 @@ 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); + // resize backing store + 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 - 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, + if (gtk_widget_get_realized (widget)) { + gdk_window_move_resize (gtk_widget_get_window (widget), + allocation->x, allocation->y, + allocation->width, allocation->height); + } + + if (allocation->width > old_allocation.width) { + canvas->requestRedraw(canvas->_x0 + old_allocation.width, + canvas->_y0, canvas->_x0 + allocation->width, canvas->_y0 + allocation->height); } - if (allocation->height > widg_allocation.height) { - canvas->requestRedraw(0, - canvas->_y0 + widg_allocation.height, + if (allocation->height > old_allocation.height) { + canvas->requestRedraw(canvas->_x0, + canvas->_y0 + old_allocation.height, canvas->_x0 + allocation->width, canvas->_y0 + allocation->height); } - - gtk_widget_set_allocation (widget, allocation); - - if (gtk_widget_get_realized (widget)) { - gdk_window_move_resize (gtk_widget_get_window (widget), - allocation->x, allocation->y, - allocation->width, allocation->height); - } } int SPCanvas::emitEvent(GdkEvent *event) @@ -1600,7 +1613,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 +1623,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_subtract_rectangle(_dirty_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 +1812,66 @@ 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_intersect(draw_dirty, canvas->_dirty_region); + cairo_region_subtract(draw_region, draw_dirty); + + // 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 + int n_rects = cairo_region_num_rectangles(draw_dirty); + for (int i = 0; i < n_rects; ++i) { + cairo_rectangle_int_t crect; + cairo_region_get_rectangle(draw_dirty, i, &crect); + canvas->requestRedraw(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height); + } + 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 @@ -1889,39 +1923,18 @@ int SPCanvas::paint() sp_canvas_item_invoke_update(_root, Geom::identity(), 0); _need_update = FALSE; } - if (!_need_redraw) { return TRUE; } - Cairo::RefPtr 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(); - - 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(_dirty_region); + for (int i = 0; i < n_rects; ++i) { + cairo_rectangle_int_t crect; + cairo_region_get_rectangle(_dirty_region, i, &crect); + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + // Aborted + return FALSE; + }; } _need_redraw = FALSE; @@ -2012,21 +2025,46 @@ 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; + + cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; + cairo_region_intersect_rectangle(_dirty_region, &crect); + if (SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed) { SP_CANVAS_ITEM_GET_CLASS(_root)->viewbox_changed(_root, new_area); } - if (!clear) { + if (clear) { + requestRedraw(_x0, _y0, allocation.width, allocation.height); + } else { // 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 + + if (dx > 0) { + requestRedraw(_x0 + allocation.width - dx, _y0, _x0 + allocation.width, _y0 + allocation.height); + } else if (dx < 0) { + requestRedraw(_x0, _y0, _x0 - dx, _y0 + allocation.height); + } + if (dy > 0) { + requestRedraw(_x0, _y0 + allocation.height - dy, _x0 + allocation.width, _y0 + allocation.height); + } else if (dy < 0) { + requestRedraw(_x0, _y0, _x0 + allocation.width, _y0 - dy); + } } } @@ -2168,42 +2206,6 @@ 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); @@ -2211,20 +2213,11 @@ void SPCanvas::dirtyRect(Geom::IntRect const &area) { 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 Date: Tue, 12 Apr 2016 16:38:25 +0100 Subject: desktop-widget: Fix background color setting #Hackfest2016 (bzr r14796) --- src/widgets/desktop-widget.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 3fa607820..e899f9af1 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; -- cgit v1.2.3 From aea4803e114c264636addd9e8fea9c179ad06a62 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 12 Apr 2016 16:42:30 +0100 Subject: desktop-widget: Fix deprecated gtk_widget_reparent usage #Hackfest2016 (bzr r14797) --- src/widgets/desktop-widget.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index e899f9af1..bf9e7e272 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1693,7 +1693,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); @@ -1701,7 +1702,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 ); -- cgit v1.2.3 From 85f115d1abec77f4e574b1e59c074509031f23a2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 12 Apr 2016 16:46:20 +0100 Subject: Update copyright notices on display/sp-canvas.(h|cpp) (bzr r14798) --- src/display/sp-canvas.cpp | 2 ++ src/display/sp-canvas.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 2dced2512..8222f83ba 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -8,9 +8,11 @@ * fred * bbyak * Jon A. Cruz + * Krzysztof Kosiński * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002-2006 authors + * Copyright (C) 2016 Google * * Released under GNU GPL, read the file 'COPYING' for more information */ diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 1f357a351..b626beedb 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -11,9 +11,11 @@ * Raph Levien * Lauris Kaplinski * Jon A. Cruz + * Krzysztof Kosiński * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2016 Google * * Released under GNU GPL, read the file 'COPYING' for more information */ -- cgit v1.2.3 From b3f4e955d1e0e8695e81a8dd9bb0b70f1a6bf7f1 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 12 Apr 2016 17:00:58 +0100 Subject: sp-canvas: Disable deprecated double-buffering #Hackfest2016 (bzr r14799) --- src/display/sp-canvas.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 8222f83ba..598f45a7a 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -937,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; @@ -1569,11 +1568,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]); -- cgit v1.2.3 From fe975a9b3c5603fe2b2d0491de3bbfe1e4bf0233 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Tue, 12 Apr 2016 17:01:58 +0100 Subject: Fork GtkImageMenuItem and remove show_image boolean because we always want to show menu. (bzr r14800) --- src/ui/interface.cpp | 12 + src/widgets/Makefile_insert | 6 + src/widgets/imagemenuitem.c | 1071 +++++++++++++++++++++++++++++++++++++++++++ src/widgets/imagemenuitem.h | 81 ++++ src/widgets/ink-action.cpp | 20 +- 5 files changed, 1189 insertions(+), 1 deletion(-) create mode 100644 src/widgets/imagemenuitem.c create mode 100644 src/widgets/imagemenuitem.h (limited to 'src') diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 8639861f8..6d0a85f13 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/imagemenuitem.h" +#endif + #include #include @@ -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/widgets/Makefile_insert b/src/widgets/Makefile_insert index 6913f4a58..10462a859 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/imagemenuitem.c \ + widgets/imagemenuitem.h +endif + ink_common_sources += \ widgets/arc-toolbar.cpp \ widgets/arc-toolbar.h \ diff --git a/src/widgets/imagemenuitem.c b/src/widgets/imagemenuitem.c new file mode 100644 index 000000000..86c44fe32 --- /dev/null +++ b/src/widgets/imagemenuitem.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 . + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. + * Forked by . Icons in menus are important to us. + */ + +#include "config.h" + +#include +#include + +#include "widgets/imagemenuitem.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/imagemenuitem.h b/src/widgets/imagemenuitem.h new file mode 100644 index 000000000..61cc48f3a --- /dev/null +++ b/src/widgets/imagemenuitem.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 . + */ + +/* + * 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 + +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..01aa4957a 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 -#include + #include "widgets/ink-action.h" #include "widgets/button.h" +#include + +#if GTK_CHECK_VERSION(3,0,0) + // Fork of gtk-imagemenuitem to continue support + #include "widgets/imagemenuitem.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; -- cgit v1.2.3 From 42727c90c85049a17b192530ec3f96bac3054e15 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 12 Apr 2016 23:33:42 +0100 Subject: desktop-widget: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14802) --- src/widgets/desktop-widget.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index bf9e7e272..759be551f 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -700,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), " 0.00 " ); - 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), " 0.00 " ); gtk_label_set_markup( GTK_LABEL(dtw->coord_status_y), " 0.00 " ); - 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); @@ -764,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), _("Welcome to Inkscape! Use shape or freehand tools to create objects; use selector (arrow) to move or transform them.")); -- cgit v1.2.3 From 18444221922cb85250c29eeb43850077c9f5f88c Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 12 Apr 2016 23:37:22 +0100 Subject: ege-adjustment-action: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14803) --- src/widgets/ege-adjustment-action.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') 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 ); } } -- cgit v1.2.3 From 936d8b575539c41d1f45688beea20bb8038b38be Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 12 Apr 2016 23:41:33 +0100 Subject: gradient-vector: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14804) --- src/widgets/gradient-vector.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') 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); -- cgit v1.2.3 From 9c951f1140577582dde039e5c1abb934f3b97dec Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 00:04:28 +0100 Subject: spw-utilities: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14805) --- src/widgets/spw-utilities.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp index 7030753a5..2cad395e7 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) -- cgit v1.2.3 From 5d51cbdde8990a564d60e38ab121b31b97ba110d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 00:22:35 +0100 Subject: ege-select-one-action: Fix deprecated GtkAlignment #Hackfest2016 (bzr r14806) --- src/widgets/ege-select-one-action.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') 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) ) { -- cgit v1.2.3 From 12dfd72d7b2ed18dbf894d24c76d63784030eb31 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 08:37:07 +0100 Subject: clonetiler: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14807) --- src/ui/dialog/clonetiler.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index fbd050f8e..fa53041d3 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); } -- cgit v1.2.3 From 5cebe28e2fa5ca6ee27e43579596f5aad43273f5 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 08:43:53 +0100 Subject: clonetiler: Fix deprecated GtkAlignment #Hackfest2016 (bzr r14808) --- src/ui/dialog/clonetiler.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index fa53041d3..9656878e0 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -2866,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 } -- cgit v1.2.3 From 1ed89e14a0101dc5f57dfde75895a5e00e0ee37d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 09:34:40 +0100 Subject: color-icc-selector: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14809) --- src/ui/widget/color-icc-selector.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3 From e12e3b0f5a6382aadd604101c68cb3c66658167e Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 09:41:56 +0100 Subject: color-notebook: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14810) --- src/ui/widget/color-notebook.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') 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)); -- cgit v1.2.3 From eff7c5e5ab8ed2f381b7dbb6edfd1c7062afc812 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 09:47:09 +0100 Subject: color-scales: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14812) --- src/ui/widget/color-scales.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') 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(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) -- cgit v1.2.3 From 2656d1c2c4f35261da9cd40a94417426e5c6d8e4 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 10:03:28 +0100 Subject: ink-action: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14813) --- src/widgets/ink-action.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src') diff --git a/src/widgets/ink-action.cpp b/src/widgets/ink-action.cpp index 01aa4957a..44ba5c7f9 100644 --- a/src/widgets/ink-action.cpp +++ b/src/widgets/ink-action.cpp @@ -392,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 ); @@ -423,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 } } @@ -595,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); -- cgit v1.2.3 From 0ed6ffcc46be15caa8974c2778ec2b86e6139ab2 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 13 Apr 2016 11:11:33 +0200 Subject: Restore ability to set unitless 'line-height'. Hackfest 2016 Note: Rendering with 'line-height' with units is buggy. (bzr r14814) --- src/widgets/text-toolbar.cpp | 79 +++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 31 deletions(-) (limited to 'src') 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 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( 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 ); -- cgit v1.2.3 From d9cab02baeddb4f97a34a72e1b0de97b13a3037a Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 10:13:05 +0100 Subject: ink-comboboxentry-action: Fix deprecated gtk_misc_set_alignment #Hackfest2016 (bzr r14815) --- src/widgets/ink-comboboxentry-action.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src') 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 : -- cgit v1.2.3 From a78262c248224a8e486985de4736b20d2e9e3ff2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 13 Apr 2016 10:28:57 +0100 Subject: Simplify SPCanvas by tracking the clean region instead of the dirty region. #Hackfest2016 (bzr r14816) --- src/display/sp-canvas.cpp | 113 ++++++++++++++++------------------------------ src/display/sp-canvas.h | 5 +- 2 files changed, 42 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 598f45a7a..644da8d5a 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -12,7 +12,7 @@ * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002-2006 authors - * Copyright (C) 2016 Google + * Copyright (C) 2016 Google Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -958,7 +958,7 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_drawing_disabled = false; canvas->_backing_store = NULL; - canvas->_dirty_region = cairo_region_create(); + canvas->_clean_region = cairo_region_create(); canvas->_forced_redraw_count = 0; canvas->_forced_redraw_limit = -1; @@ -971,12 +971,11 @@ static void sp_canvas_init(SPCanvas *canvas) 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; + // 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; @@ -1003,9 +1002,9 @@ void SPCanvas::dispose(GObject *object) cairo_surface_destroy(canvas->_backing_store); canvas->_backing_store = NULL; } - if (canvas->_dirty_region) { - cairo_region_destroy(canvas->_dirty_region); - canvas->_dirty_region = NULL; + if (canvas->_clean_region) { + cairo_region_destroy(canvas->_clean_region); + canvas->_clean_region = NULL; } canvas->shutdownTransients(); @@ -1150,7 +1149,7 @@ void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation Geom::IntRect new_area = Geom::IntRect::from_xywh(canvas->_x0, canvas->_y0, allocation->width, allocation->height); - // resize backing store + // 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) { @@ -1174,19 +1173,7 @@ void SPCanvas::handle_size_allocate(GtkWidget *widget, GtkAllocation *allocation allocation->x, allocation->y, allocation->width, allocation->height); } - - if (allocation->width > old_allocation.width) { - canvas->requestRedraw(canvas->_x0 + old_allocation.width, - canvas->_y0, - canvas->_x0 + allocation->width, - canvas->_y0 + allocation->height); - } - if (allocation->height > old_allocation.height) { - canvas->requestRedraw(canvas->_x0, - canvas->_y0 + old_allocation.height, - canvas->_x0 + allocation->width, - canvas->_y0 + allocation->height); - } + canvas->addIdle(); } int SPCanvas::emitEvent(GdkEvent *event) @@ -1622,7 +1609,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_surface_destroy(imgs); cairo_rectangle_int_t crect = { paint_rect.left(), paint_rect.right(), paint_rect.width(), paint_rect.height() }; - cairo_region_subtract_rectangle(_dirty_region, &crect); + 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()); @@ -1826,8 +1813,8 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) { cairo_rectangle_list_destroy(rects); cairo_region_t *draw_dirty = cairo_region_copy(draw_region); - cairo_region_intersect(draw_dirty, canvas->_dirty_region); - cairo_region_subtract(draw_region, draw_dirty); + 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)) { @@ -1846,11 +1833,8 @@ gboolean SPCanvas::handle_draw(GtkWidget *widget, cairo_t *cr) { } // Render the dirty portion in the background - int n_rects = cairo_region_num_rectangles(draw_dirty); - for (int i = 0; i < n_rects; ++i) { - cairo_rectangle_int_t crect; - cairo_region_get_rectangle(draw_dirty, i, &crect); - canvas->requestRedraw(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height); + if (!cairo_region_is_empty(draw_dirty)) { + canvas->addIdle(); } cairo_region_destroy(draw_region); cairo_region_destroy(draw_dirty); @@ -1920,22 +1904,23 @@ int SPCanvas::paint() sp_canvas_item_invoke_update(_root, Geom::identity(), 0); _need_update = FALSE; } - if (!_need_redraw) { - return TRUE; - } - int n_rects = cairo_region_num_rectangles(_dirty_region); + 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); + + 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(_dirty_region, i, &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; @@ -2035,39 +2020,32 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll cairo_surface_destroy(_backing_store); _backing_store = new_backing_store; - cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; - cairo_region_intersect_rectangle(_dirty_region, &crect); + 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); } - if (clear) { - requestRedraw(_x0, _y0, allocation.width, allocation.height); - } else { + if (!clear) { // scrolling without zoom; redraw only the newly exposed areas if ((dx != 0) || (dy != 0)) { if (gtk_widget_get_realized(GTK_WIDGET(this))) { gdk_window_scroll(getWindow(this), -dx, -dy); } } - - if (dx > 0) { - requestRedraw(_x0 + allocation.width - dx, _y0, _x0 + allocation.width, _y0 + allocation.height); - } else if (dx < 0) { - requestRedraw(_x0, _y0, _x0 - dx, _y0 + allocation.height); - } - if (dy > 0) { - requestRedraw(_x0, _y0 + allocation.height - dy, _x0 + allocation.width, _y0 + allocation.height); - } else if (dy < 0) { - requestRedraw(_x0, _y0, _x0 + allocation.width, _y0 - dy); - } } + addIdle(); } void SPCanvas::updateNow() { - if (_need_update || _need_redraw) { + if (_need_update) { doUpdate(); } } @@ -2080,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(); } /** @@ -2204,7 +2172,6 @@ inline int sp_canvas_tile_ceil(int x) } void SPCanvas::dirtyRect(Geom::IntRect const &area) { - _need_redraw = TRUE; markRect(area, 1); } @@ -2212,9 +2179,9 @@ void SPCanvas::markRect(Geom::IntRect const &area, uint8_t val) { cairo_rectangle_int_t crect = { area.left(), area.top(), area.width(), area.height() }; if (val) { - cairo_region_union_rectangle(_dirty_region, &crect); + cairo_region_subtract_rectangle(_clean_region, &crect); } else { - cairo_region_subtract_rectangle(_dirty_region, &crect); + cairo_region_union_rectangle(_clean_region, &crect); } } diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index b626beedb..a1f8d0a1a 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -15,7 +15,7 @@ * * Copyright (C) 1998 The Free Software Foundation * Copyright (C) 2002 Lauris Kaplinski - * Copyright (C) 2016 Google + * Copyright (C) 2016 Google Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -182,7 +182,7 @@ public: /* Area that needs redrawing, stored as a microtile array */ cairo_surface_t *_backing_store; - cairo_region_t *_dirty_region; + 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; -- cgit v1.2.3 From 0336a2a6926411517cdba3baa93a0bd67411cfe1 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Wed, 13 Apr 2016 11:46:28 +0200 Subject: Fix cmake build (bzr r14818) --- src/ui/interface.cpp | 2 +- src/widgets/CMakeLists.txt | 8 + src/widgets/Makefile_insert | 4 +- src/widgets/image-menu-item.c | 1071 +++++++++++++++++++++++++++++++++++++++++ src/widgets/image-menu-item.h | 81 ++++ src/widgets/imagemenuitem.c | 1071 ----------------------------------------- src/widgets/imagemenuitem.h | 81 ---- src/widgets/ink-action.cpp | 2 +- 8 files changed, 1164 insertions(+), 1156 deletions(-) create mode 100644 src/widgets/image-menu-item.c create mode 100644 src/widgets/image-menu-item.h delete mode 100644 src/widgets/imagemenuitem.c delete mode 100644 src/widgets/imagemenuitem.h (limited to 'src') diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 6d0a85f13..a16bbc472 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -80,7 +80,7 @@ #include "ui/dialog/layer-properties.h" #if GTK_CHECK_VERSION(3,0,0) - #include "widgets/imagemenuitem.h" + #include "widgets/image-menu-item.h" #endif #include 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 10462a859..2ee0f7002 100644 --- a/src/widgets/Makefile_insert +++ b/src/widgets/Makefile_insert @@ -2,8 +2,8 @@ if WITH_GTKMM_3_0 ink_common_sources += \ - widgets/imagemenuitem.c \ - widgets/imagemenuitem.h + widgets/image-menu-item.c \ + widgets/image-menu-item.h endif ink_common_sources += \ 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 . + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. + * Forked by . Icons in menus are important to us. + */ + +#include "config.h" + +#include +#include + +#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 . + */ + +/* + * 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 + +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/imagemenuitem.c b/src/widgets/imagemenuitem.c deleted file mode 100644 index 86c44fe32..000000000 --- a/src/widgets/imagemenuitem.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* 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 . - */ - -/* - * Modified by the GTK+ Team and others 1997-2000. - * Forked by . Icons in menus are important to us. - */ - -#include "config.h" - -#include -#include - -#include "widgets/imagemenuitem.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/imagemenuitem.h b/src/widgets/imagemenuitem.h deleted file mode 100644 index 61cc48f3a..000000000 --- a/src/widgets/imagemenuitem.h +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 . - */ - -/* - * 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 - -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 44ba5c7f9..ace99d9aa 100644 --- a/src/widgets/ink-action.cpp +++ b/src/widgets/ink-action.cpp @@ -11,7 +11,7 @@ #if GTK_CHECK_VERSION(3,0,0) // Fork of gtk-imagemenuitem to continue support - #include "widgets/imagemenuitem.h" + #include "widgets/image-menu-item.h" #endif -- cgit v1.2.3 From 1eacfbf37731e918de1690b1e614440c4e3d9afe Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 11:19:33 +0100 Subject: spw-utilities: Fix deprecated gtk_widget_override_font #Hackfest2016 (bzr r14819) --- src/widgets/spw-utilities.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp index 2cad395e7..89ab76585 100644 --- a/src/widgets/spw-utilities.cpp +++ b/src/widgets/spw-utilities.cpp @@ -255,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(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 @@ -268,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 -- cgit v1.2.3 From 82014e41c1e158e3b8d3f4ca9af9834400ca8f91 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Wed, 13 Apr 2016 11:21:25 +0100 Subject: gimpcolorwheel: Fix deprecated gtk_widget_style_attach #Hackfest2016 (bzr r14820) --- src/ui/widget/gimpcolorwheel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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 -- cgit v1.2.3