/* * Copyright (c) 2011 Red Hat, Inc. * Copyright (c) 2012 Igalia, S.L. * * This program 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 program 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 program; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Based on gd-toggle-pixbuf-renderer by Cosimo Cecchi * */ #include "config.h" #include "ephy-removable-pixbuf-renderer.h" #include "ephy-widgets-type-builtins.h" G_DEFINE_TYPE (EphyRemovablePixbufRenderer, ephy_removable_pixbuf_renderer, GD_TYPE_TOGGLE_PIXBUF_RENDERER); enum { DELETE_CLICKED, LAST_SIGNAL }; enum { PROP_0 = 0, PROP_RENDER_POLICY }; static guint signals[LAST_SIGNAL] = { 0 }; struct _EphyRemovablePixbufRendererPrivate { EphyRemovablePixbufRenderPolicy policy; GdkPixbuf *close_icon; }; static void get_icon_rectangle (GtkWidget *widget, GtkCellRenderer *cell, const GdkRectangle *cell_area, GdkPixbuf *icon, GdkRectangle *rectangle) { GtkTextDirection direction; gint x_offset, y_offset, xpad, ypad; gint icon_size; gint w = 0, h = 0; GdkPixbuf *pixbuf; gtk_cell_renderer_get_padding (cell, &xpad, &ypad); direction = gtk_widget_get_direction (widget); icon_size = gdk_pixbuf_get_width (icon); g_object_get (cell, "pixbuf", &pixbuf, NULL); if (pixbuf) { w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); g_object_unref (pixbuf); } x_offset = (cell_area->width - w)/2 + 10; y_offset = (cell_area->height - h)/2 + 9; if (direction == GTK_TEXT_DIR_RTL) x_offset += xpad; else x_offset = cell_area->width - icon_size - xpad - x_offset; rectangle->x = cell_area->x + x_offset; rectangle->y = cell_area->y + ypad + y_offset; rectangle->width = rectangle->height = icon_size; } static void ephy_removable_pixbuf_renderer_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { GtkStyleContext *context; EphyRemovablePixbufRenderer *self = EPHY_REMOVABLE_PIXBUF_RENDERER (cell); GdkRectangle icon_area; GTK_CELL_RENDERER_CLASS (ephy_removable_pixbuf_renderer_parent_class)->render (cell, cr, widget, background_area, cell_area, flags); if (self->priv->policy == EPHY_REMOVABLE_PIXBUF_RENDER_NEVER || (self->priv->policy == EPHY_REMOVABLE_PIXBUF_RENDER_PRELIT && !(flags & GTK_CELL_RENDERER_PRELIT))) return; get_icon_rectangle (widget, cell, cell_area, self->priv->close_icon, &icon_area); context = gtk_widget_get_style_context (widget); gtk_render_icon (context, cr, self->priv->close_icon, icon_area.x, icon_area.y); } static gboolean ephy_removable_pixbuf_renderer_activate (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { GdkRectangle icon_area; GdkEventButton *ev = (GdkEventButton *) gtk_get_current_event(); EphyRemovablePixbufRendererPrivate *priv = EPHY_REMOVABLE_PIXBUF_RENDERER (cell)->priv; if (priv->policy == EPHY_REMOVABLE_PIXBUF_RENDER_NEVER) return FALSE; get_icon_rectangle (widget, cell, cell_area, priv->close_icon, &icon_area); if (icon_area.x <= ev->x && ev->x <= icon_area.x + icon_area.width && icon_area.y <= ev->y && ev->y <= icon_area.y + icon_area.height) { g_signal_emit (cell, signals [DELETE_CLICKED], 0, path); return TRUE; } return FALSE; } static void ephy_removable_pixbuf_renderer_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { EphyRemovablePixbufRenderer *self = EPHY_REMOVABLE_PIXBUF_RENDERER (object); switch (property_id) { case PROP_RENDER_POLICY: g_value_set_enum (value, self->priv->policy); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ephy_removable_pixbuf_renderer_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { EphyRemovablePixbufRenderer *self = EPHY_REMOVABLE_PIXBUF_RENDERER (object); switch (property_id) { case PROP_RENDER_POLICY: self->priv->policy = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void ephy_removable_pixbuf_renderer_dispose (GObject *object) { EphyRemovablePixbufRendererPrivate *priv = EPHY_REMOVABLE_PIXBUF_RENDERER (object)->priv; if (priv->close_icon) g_clear_object (&priv->close_icon); G_OBJECT_CLASS (ephy_removable_pixbuf_renderer_parent_class)->dispose (object); } static void ephy_removable_pixbuf_renderer_class_init (EphyRemovablePixbufRendererClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); GtkCellRendererClass *crclass = GTK_CELL_RENDERER_CLASS (klass); crclass->render = ephy_removable_pixbuf_renderer_render; crclass->activate = ephy_removable_pixbuf_renderer_activate; oclass->get_property = ephy_removable_pixbuf_renderer_get_property; oclass->set_property = ephy_removable_pixbuf_renderer_set_property; oclass->dispose = ephy_removable_pixbuf_renderer_dispose; g_object_class_install_property (oclass, PROP_RENDER_POLICY, g_param_spec_enum ("render-policy", "Render policy", "The rendering policy for the close icon in the renderer", EPHY_TYPE_REMOVABLE_PIXBUF_RENDER_POLICY, EPHY_REMOVABLE_PIXBUF_RENDER_PRELIT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); signals[DELETE_CLICKED] = g_signal_new ("delete-clicked", G_OBJECT_CLASS_TYPE (oclass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private (klass, sizeof (EphyRemovablePixbufRendererPrivate)); } static void ephy_removable_pixbuf_renderer_init (EphyRemovablePixbufRenderer *self) { GtkIconTheme *icon_theme; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EPHY_TYPE_REMOVABLE_PIXBUF_RENDERER, EphyRemovablePixbufRendererPrivate); g_object_set (self, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); icon_theme = gtk_icon_theme_get_default (); self->priv->close_icon = gtk_icon_theme_load_icon (icon_theme, "window-close-symbolic", 24, 0, NULL); } GtkCellRenderer * ephy_removable_pixbuf_renderer_new (void) { return g_object_new (EPHY_TYPE_REMOVABLE_PIXBUF_RENDERER, NULL); }