/*************************************************************************** * gtkcellrenderertextpixbuf.c * * Wed May 25 17:39:49 2005 * Copyright 2005 User * Email ****************************************************************************/ #include "gtkcellrenderertextpixbuf.h" static void gtk_cell_renderer_text_pixbuf_init(GtkCellRendererTextPixbuf *celltextpixbuf); static void gtk_cell_renderer_text_pixbuf_class_init(GtkCellRendererTextPixbufClass *class); static void gtk_cell_renderer_text_pixbuf_finalize(GObject *object); static void gtk_cell_renderer_text_pixbuf_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void gtk_cell_renderer_text_pixbuf_set_property(GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void gtk_cell_renderer_text_pixbuf_get_size(GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void gtk_cell_renderer_text_pixbuf_render(GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags); #define GTK_CELL_RENDERER_TEXT_PIXBUF_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, GtkCellRendererTextPixbufPrivate)) /* typedef struct _GtkCellRendererTextPixbufPrivate GtkCellRendererTextPixbufPrivate; struct _GtkCellRendererTextPixbufPrivate { GList *pixbufs; gboolean align_left, use_mask; gint text_x_offset, text_y_offset, text_width, text_height, distance, padding; gulong mask; };*/ enum { PROP_0, PROP_PIXBUFALIGN, PROP_PIXBUFLIST, PROP_MASKSET, PROP_MASK, PROP_DISTANCE, PROP_PADDING }; G_DEFINE_TYPE(GtkCellRendererTextPixbuf, gtk_cell_renderer_text_pixbuf, GTK_TYPE_CELL_RENDERER_TEXT); static gpointer parent_class; /* GType gtk_cell_renderer_text_pixbuf_get_type(void) { static GType cell_text_pixbuf_type = 0; if (!cell_text_pixbuf_type) { static const GTypeInfo cell_text_pixbuf_info = { sizeof(GtkCellRendererTextPixbufClass), NULL, // base init NULL, // base finalize (GClassInitFunc)gtk_cell_renderer_text_pixbuf_class_init, NULL, // class finalize NULL, // class data sizeof (GtkCellRendererText), 0, // n_preallocs (GInstanceInitFunc) gtk_cell_renderer_text_pixbuf_init, }; cell_text_pixbuf_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "GtkCellRendererTextPixbuf", &cell_text_pixbuf_info, 0); } return cell_text_pixbuf_type; } */ static void gtk_cell_renderer_text_pixbuf_init(GtkCellRendererTextPixbuf *celltextpixbuf) { celltextpixbuf->align_left = FALSE; celltextpixbuf->pixbufs = NULL; celltextpixbuf->use_mask = FALSE; celltextpixbuf->mask = 0; celltextpixbuf->distance = 0; celltextpixbuf->padding = 0; celltextpixbuf->pixbuflen = 0; } static void gtk_cell_renderer_text_pixbuf_class_init(GtkCellRendererTextPixbufClass *class) { GObjectClass *object_class = G_OBJECT_CLASS(class); GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(class); parent_class = g_type_class_peek_parent(class); // set all functions object_class->finalize = gtk_cell_renderer_text_pixbuf_finalize; object_class->get_property = gtk_cell_renderer_text_pixbuf_get_property; object_class->set_property = gtk_cell_renderer_text_pixbuf_set_property; cell_class->get_size = gtk_cell_renderer_text_pixbuf_get_size; cell_class->render = gtk_cell_renderer_text_pixbuf_render; g_object_class_install_property(object_class, PROP_PIXBUFALIGN, g_param_spec_boolean("pixbufalign", "Pixbuf Alignment", "How to align the pixbuf list", TRUE, G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_PIXBUFLIST, g_param_spec_pointer("pixbuflist", "Pixbuf Alignment", "A GList defining the pixbufs", G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_MASKSET, g_param_spec_boolean("mask-set", "Use the mask", "Whether pixbuf should be displayed using a mask", FALSE, G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_MASK, g_param_spec_ulong("mask", "The bit mask", "A bit mask that defines the displayed pixbufs", 0, 0xFFFFFFFF, 0, G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_DISTANCE, g_param_spec_int("distance", "Distance between text and pixbufs", "The Distance between the text and the pixbufs in pixels", 0, 0xFFFF, 0, G_PARAM_READWRITE)); g_object_class_install_property(object_class, PROP_PADDING, g_param_spec_int("pixbufpadding", "Padding between pixbufs", "The Padding between the pixbufs", 0, 0xFFFF, 0, G_PARAM_READWRITE)); } static void gtk_cell_renderer_text_pixbuf_finalize(GObject *object) { GtkCellRendererTextPixbuf* cell = GTK_CELL_RENDERER_TEXT_PIXBUF(object); g_free(cell->pixbufs); // (* G_OBJECT_CLASS (parent_class)->finalize) (object); G_OBJECT_CLASS(gtk_cell_renderer_text_pixbuf_parent_class)->finalize(object); } static void gtk_cell_renderer_text_pixbuf_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { GtkCellRendererTextPixbuf *cell; g_return_if_fail(GTK_IS_CELL_RENDERER_TEXT_PIXBUF(object)); cell = GTK_CELL_RENDERER_TEXT_PIXBUF(object); switch(param_id) { case PROP_PIXBUFALIGN: g_value_set_boolean(value, cell->align_left); break; case PROP_PIXBUFLIST: g_value_set_pointer(value, cell->pixbufs); break; case PROP_MASKSET: g_value_set_boolean(value, cell->use_mask); break; case PROP_MASK: g_value_set_ulong(value, cell->mask); break; case PROP_DISTANCE: g_value_set_int(value, cell->distance); break; case PROP_PADDING: g_value_set_int(value, cell->padding); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); } } static void gtk_cell_renderer_text_pixbuf_set_property(GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { GList *search, *newList; int i; GtkCellRendererTextPixbuf *cell; g_return_if_fail(GTK_IS_CELL_RENDERER_TEXT_PIXBUF(object)); cell = GTK_CELL_RENDERER_TEXT_PIXBUF(object); switch(param_id) { case PROP_PIXBUFALIGN: cell->align_left = g_value_get_boolean(value); //g_object_notify(object, "pixbufalign"); break; case PROP_PIXBUFLIST: /* if (cell->pixbufs) g_list_free(cell->pixbufs);*/ /* cell->pixbufs = NULL; current = &cell->pixbufs; // please don't ask about this shit. // The following is nothing else than a g_list_copy. // I tried for hours and for some reason g_list_copy freezes // user input later ~sometimes~. This is a dirty workaround. for (search = (GList*)g_value_get_pointer(value); search; search = search->next) { *current = (GList*)g_malloc0(sizeof(GList)); (*current)->data = search->data; current = &(*current)->next; } *current = NULL; */ //cell->pixbufs = g_list_copy((GList*)g_value_get_pointer(value)); // g_object_notify(object, "pixbuflist"); newList = (GList*)g_value_get_pointer(value); cell->pixbuflen = g_list_length(newList); if (cell->pixbufs) g_free(cell->pixbufs); cell->pixbufs = g_malloc0(sizeof(GdkPixbuf*)*cell->pixbuflen); i = 0; for (search = newList; search; search = search->next) { cell->pixbufs[i] = (GdkPixbuf*)search->data; i++; } break; case PROP_MASKSET: cell->use_mask = g_value_get_boolean(value); // g_object_notify(object, "mask-set"); break; case PROP_MASK: cell->mask = g_value_get_ulong(value); // g_object_notify(object, "mask"); break; case PROP_DISTANCE: cell->distance = g_value_get_int(value); // g_object_notify(object, "distance"); break; case PROP_PADDING: cell->padding = g_value_get_int(value); // g_object_notify(object, "pixbufpadding"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); } } GtkCellRenderer *gtk_cell_renderer_text_pixbuf_new (void) { return g_object_new(GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, NULL); } static void gtk_cell_renderer_text_pixbuf_get_size(GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { GtkCellRendererTextPixbuf *priv; GdkPixbuf *pixbuf; gint tmpheight, num; gboolean display_pixbuf; priv = GTK_CELL_RENDERER_TEXT_PIXBUF(cell); GTK_CELL_RENDERER_CLASS(parent_class)->get_size(cell, widget, cell_area, x_offset, y_offset, width, height); // get the new width if (width) { priv->text_width = *width; for (num = 0; numpixbuflen; num++) { display_pixbuf = (priv->use_mask && (priv->mask & (1<use_mask; if (priv->pixbufs[num] && display_pixbuf) { pixbuf = (GdkPixbuf*)priv->pixbufs[num]; if (pixbuf) *width = *width + gdk_pixbuf_get_width(pixbuf) + priv->padding; } } if (*width != priv->text_width) *width = *width + priv->distance - priv->padding; } // get the new height if (height) { priv->text_height = *height; for (num = 0; numpixbuflen; num++) { display_pixbuf = (priv->use_mask && (priv->mask & (1<use_mask; if (priv->pixbufs[num] && display_pixbuf) { pixbuf = (GdkPixbuf*)priv->pixbufs[num]; if (pixbuf) { tmpheight = gdk_pixbuf_get_height(pixbuf); if (tmpheight > *height) *height = tmpheight; } } } } if (y_offset) *y_offset = 0; } static void gtk_cell_renderer_text_pixbuf_render(GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) { GtkCellRendererTextPixbuf *priv; GdkPixbuf *pixbuf; gint tmp_y, num; gboolean display_pixbuf; GdkRectangle pix_rect, draw_rect; priv = GTK_CELL_RENDERER_TEXT_PIXBUF(cell); // *** render the text *** GTK_CELL_RENDERER_CLASS(parent_class)->render(cell, window, widget, background_area, cell_area, expose_area, flags); if (!priv->pixbufs) return; // *** render the pixbufs *** gtk_cell_renderer_text_pixbuf_get_size(cell, widget, cell_area, &pix_rect.x, &pix_rect.y, &pix_rect.width, &pix_rect.height); pix_rect.x+= priv->text_x_offset + priv->text_width + priv->distance + cell_area->x; pix_rect.y+= cell_area->y - priv->text_y_offset; pix_rect.width+= cell_area->width; pix_rect.height+= cell_area->height; for (num = 0; numpixbuflen; num++) { display_pixbuf = (priv->use_mask && (priv->mask & (1<use_mask; if (priv->pixbufs[num] && display_pixbuf) { pixbuf = (GdkPixbuf*)priv->pixbufs[num]; if (pixbuf) { pix_rect.width = gdk_pixbuf_get_width(pixbuf); pix_rect.height = gdk_pixbuf_get_height(pixbuf); tmp_y = pix_rect.y; pix_rect.y+= (cell_area->height - pix_rect.height) / 2; if (gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) && gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect)) gdk_draw_pixbuf(window, widget->style->black_gc, pixbuf, draw_rect.x - pix_rect.x, draw_rect.y - pix_rect.y, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height, GDK_RGB_DITHER_NORMAL, 0, 0); pix_rect.y = tmp_y; pix_rect.x+= pix_rect.width + priv->padding; } } } } GdkPixbuf** gtk_cell_renderer_text_pixbuf_get_list(GtkCellRendererTextPixbuf* renderer) { return renderer->pixbufs; } void gtk_cell_renderer_text_pixbuf_set_list(GtkCellRendererTextPixbuf* renderer, GList* list) { g_object_set(G_OBJECT(renderer), "pixbuflist", list, NULL); } void gtk_cell_renderer_text_pixbuf_set_use_mask(GtkCellRendererTextPixbuf* renderer, gboolean state) { g_object_set(G_OBJECT(renderer), "mask-set", state, NULL); } gboolean gtk_cell_renderer_text_pixbuf_get_use_mask(GtkCellRendererTextPixbuf* renderer) { return renderer->use_mask; } void gtk_cell_renderer_text_pixbuf_set_mask(GtkCellRendererTextPixbuf* renderer, gulong mask) { g_object_set(G_OBJECT(renderer), "mask", mask, NULL); } gulong gtk_cell_renderer_text_pixbuf_get_mask(GtkCellRendererTextPixbuf* renderer) { return renderer->mask; } void gtk_cell_renderer_text_pixbuf_set_distance(GtkCellRendererTextPixbuf* renderer, gint distance) { g_object_set(G_OBJECT(renderer), "distance", distance, NULL); } gint gtk_cell_renderer_text_pixbuf_get_distance(GtkCellRendererTextPixbuf* renderer) { return renderer->distance; } void gtk_cell_renderer_text_pixbuf_set_padding(GtkCellRendererTextPixbuf* renderer, gint padding) { g_object_set(G_OBJECT(renderer), "pixbufpadding", padding, NULL); } gint gtk_cell_renderer_text_pixbuf_get_padding(GtkCellRendererTextPixbuf* renderer) { return renderer->padding; }