static void internal_text_get_size_layout(GtkCellRenderer *cell, GtkWidget *widget, PangoLayout *layout, const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { CustomCellRendererFlexi *cellflexi = CUSTOM_CELL_RENDERER_FLEXI (cell); PangoRectangle rect; gint calc_width; gint calc_height; gint xpad; gint ypad; gfloat yalign; if (layout==NULL) layout = internal_text_create_layout(widget,cellflexi); else g_object_ref(layout); g_assert(layout!=NULL); pango_layout_get_pixel_extents(layout,NULL,&rect); gtk_cell_renderer_get_padding(cell,&xpad,&ypad); calc_width = xpad * 2 + rect.width; calc_height = ypad * 2 + rect.height; if (width) { *width = calc_width; } if (height) { *height = calc_height; } if (cell_area) { if (x_offset) { *x_offset = 0; } if (y_offset) { gtk_cell_renderer_get_alignment(cell,NULL,&yalign); *y_offset = yalign * (cell_area->height - calc_height); *y_offset = MAX (*y_offset, 0); } } g_object_unref(layout); }
static void gimp_cell_renderer_dashes_get_size (GtkCellRenderer *cell, GtkWidget *widget, const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { gfloat xalign, yalign; gint xpad, ypad; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); gtk_cell_renderer_get_padding (cell, &xpad, &ypad); if (cell_area) { if (x_offset) { gdouble align; align = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 1.0 - xalign : xalign); *x_offset = align * (cell_area->width - DASHES_WIDTH); *x_offset = MAX (*x_offset, 0) + xpad; } if (y_offset) { *y_offset = yalign * (cell_area->height - DASHES_HEIGHT); *y_offset = MAX (*y_offset, 0) + ypad; } } else { if (x_offset) *x_offset = 0; if (y_offset) *y_offset = 0; } *width = DASHES_WIDTH + 2 * xpad; *height = DASHES_HEIGHT + 2 * ypad; }
static void gossip_cell_renderer_expander_get_size (GtkCellRenderer *cell, GtkWidget *widget, const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { GossipCellRendererExpander *expander; GossipCellRendererExpanderPriv *priv; gint xpad, ypad; gfloat xalign, yalign; expander = (GossipCellRendererExpander*) cell; priv = GET_PRIV (expander); gtk_cell_renderer_get_padding (cell, &xpad, &ypad); if (cell_area) { gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); if (x_offset) { *x_offset = xalign * (cell_area->width - (priv->expander_size + (2 * xpad))); *x_offset = MAX (*x_offset, 0); } if (y_offset) { *y_offset = yalign * (cell_area->height - (priv->expander_size + (2 * ypad))); *y_offset = MAX (*y_offset, 0); } } else { if (x_offset) *x_offset = 0; if (y_offset) *y_offset = 0; } if (width) *width = xpad * 2 + priv->expander_size; if (height) *height = ypad * 2 + priv->expander_size; }
/*! \brief Calculates the window area the renderer will use */ static void ghid_cell_renderer_visibility_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { GtkStyle *style = gtk_widget_get_style (widget); gint w, h; gint xpad, ypad; gfloat xalign, yalign; gtk_cell_renderer_get_padding (cell, &xpad, &ypad); gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); w = VISIBILITY_TOGGLE_SIZE + 2 * (xpad + style->xthickness); h = VISIBILITY_TOGGLE_SIZE + 2 * (ypad + style->ythickness); if (width) *width = w; if (height) *height = h; if (cell_area) { if (x_offset) { if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) xalign = 1. - xalign; *x_offset = MAX (0, xalign * (cell_area->width - w)); } if (y_offset) *y_offset = MAX(0, yalign * (cell_area->height - h)); } }
static gint gtk_text_cell_accessible_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords) { AtkObject *parent; GtkRendererCellAccessible *gail_renderer; GtkCellRendererText *gtk_renderer; GtkRequisition min_size; GtkWidget *widget; GdkRectangle rendered_rect; PangoLayout *layout; gchar *renderer_text; gfloat xalign, yalign; gint x_offset, y_offset, index; gint xpad, ypad; gint x_window, y_window, x_toplevel, y_toplevel; gint x_temp, y_temp; gboolean ret; if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text) return -1; gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); parent = atk_object_get_parent (ATK_OBJECT (text)); g_object_get (gtk_renderer, "text", &renderer_text, NULL); if (text == NULL) { g_free (renderer_text); return -1; } if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent)) parent = atk_object_get_parent (parent); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)); g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), -1); _gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent), GTK_CELL_ACCESSIBLE (text), &rendered_rect); gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer), widget, &min_size, NULL); gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign); if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) xalign = 1.0 - xalign; x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width)); y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height)); layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text)); gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad); get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel); x_temp = x - (x_offset + rendered_rect.x + xpad) - x_window; y_temp = y - (y_offset + rendered_rect.y + ypad) - y_window; if (coords == ATK_XY_WINDOW) { x_temp += x_toplevel; y_temp += y_toplevel; } else if (coords != ATK_XY_SCREEN) index = -1; ret = pango_layout_xy_to_index (layout, x_temp * PANGO_SCALE, y_temp * PANGO_SCALE, &index, NULL); if (!ret) { if (x_temp < 0 || y_temp < 0) index = 0; else index = -1; } g_object_unref (layout); if (index == -1) { if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN) { glong length; length = g_utf8_strlen (renderer_text, -1); g_free (renderer_text); return length; } g_free (renderer_text); return index; } else { glong offset; offset = g_utf8_pointer_to_offset (renderer_text, renderer_text + index); g_free (renderer_text); return offset; } }
static void gtk_text_cell_accessible_get_character_extents (AtkText *text, gint offset, gint *x, gint *y, gint *width, gint *height, AtkCoordType coords) { GtkRendererCellAccessible *gail_renderer; GtkRequisition min_size; GtkCellRendererText *gtk_renderer; GdkRectangle rendered_rect; GtkWidget *widget; AtkObject *parent; PangoRectangle char_rect; PangoLayout *layout; gchar *renderer_text; gfloat xalign, yalign; gint x_offset, y_offset, index; gint xpad, ypad; gint x_window, y_window, x_toplevel, y_toplevel; if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text) { *x = *y = *height = *width = 0; return; } if (offset < 0 || offset >= GTK_TEXT_CELL_ACCESSIBLE (text)->cell_length) { *x = *y = *height = *width = 0; return; } gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); g_object_get (gtk_renderer, "text", &renderer_text, NULL); if (text == NULL) { g_free (renderer_text); return; } parent = atk_object_get_parent (ATK_OBJECT (text)); if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent)) parent = atk_object_get_parent (parent); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)); g_return_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent)); _gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent), GTK_CELL_ACCESSIBLE (text), &rendered_rect); gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer), widget, &min_size, NULL); gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign); if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) xalign = 1.0 - xalign; x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width)); y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height)); layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text)); index = g_utf8_offset_to_pointer (renderer_text, offset) - renderer_text; pango_layout_index_to_pos (layout, index, &char_rect); gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad); get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel); *x = (char_rect.x / PANGO_SCALE) + x_offset + rendered_rect.x + xpad + x_window; *y = (char_rect.y / PANGO_SCALE) + y_offset + rendered_rect.y + ypad + y_window; *height = char_rect.height / PANGO_SCALE; *width = char_rect.width / PANGO_SCALE; if (coords == ATK_XY_WINDOW) { *x -= x_toplevel; *y -= y_toplevel; } else if (coords != ATK_XY_SCREEN) { *x = 0; *y = 0; *height = 0; *width = 0; } g_free (renderer_text); g_object_unref (layout); }
static void gimp_cell_renderer_toggle_get_size (GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { GimpCellRendererToggle *toggle = GIMP_CELL_RENDERER_TOGGLE (cell); GtkStyle *style = gtk_widget_get_style (widget); gint calc_width; gint calc_height; gint pixbuf_width; gint pixbuf_height; gfloat xalign; gfloat yalign; gint xpad; gint ypad; if (! toggle->stock_id) { GTK_CELL_RENDERER_CLASS (parent_class)->get_size (cell, widget, cell_area, x_offset, y_offset, width, height); return; } gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); gtk_cell_renderer_get_padding (cell, &xpad, &ypad); if (! toggle->pixbuf) gimp_cell_renderer_toggle_create_pixbuf (toggle, widget); pixbuf_width = gdk_pixbuf_get_width (toggle->pixbuf); pixbuf_height = gdk_pixbuf_get_height (toggle->pixbuf); calc_width = (pixbuf_width + (gint) xpad * 2 + style->xthickness * 2); calc_height = (pixbuf_height + (gint) ypad * 2 + style->ythickness * 2); if (width) *width = calc_width; if (height) *height = calc_height; if (cell_area) { if (x_offset) { *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - calc_width)); *x_offset = MAX (*x_offset, 0); } if (y_offset) { *y_offset = yalign * (cell_area->height - calc_height); *y_offset = MAX (*y_offset, 0); } } }
static void gd_two_lines_renderer_get_size (GtkCellRenderer *cell, GtkWidget *widget, PangoLayout *layout_1, PangoLayout *layout_2, gint *width, gint *height, const GdkRectangle *cell_area, gint *x_offset_1, gint *x_offset_2, gint *y_offset) { GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell); gint xpad, ypad; PangoLayout *layout_one, *layout_two; GdkRectangle layout_one_rect, layout_two_rect, layout_union; if (layout_1 == NULL) { gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two); } else { layout_one = g_object_ref (layout_1); if (layout_2 != NULL) layout_two = g_object_ref (layout_2); else layout_two = NULL; } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect); if (layout_two != NULL) { pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect); layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width); layout_union.height = layout_one_rect.height + layout_two_rect.height; } else { layout_union = layout_one_rect; } if (cell_area) { gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); layout_union.width = MIN (layout_union.width, cell_area->width - 2 * xpad); layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad); if (x_offset_1) { if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad))); else *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad))); *x_offset_1 = MAX (*x_offset_1, 0); } if (x_offset_2) { if (layout_two != NULL) { if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad))); else *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad))); *x_offset_2 = MAX (*x_offset_2, 0); } else { *x_offset_2 = 0; } } if (y_offset) { *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad))); *y_offset = MAX (*y_offset, 0); } } else { if (x_offset_1) *x_offset_1 = 0; if (x_offset_2) *x_offset_2 = 0; if (y_offset) *y_offset = 0; } g_clear_object (&layout_one); g_clear_object (&layout_two); if (height) *height = ypad * 2 + layout_union.height; if (width) *width = xpad * 2 + layout_union.width; }
static GtkCellEditable* marlin_text_renderer_start_editing (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell); gint xpad, ypad; gfloat xalign, yalign; gboolean mode, visible; /* verify that we are visible & editable */ g_object_get (cell, "visible", &visible, "mode", &mode, NULL); if (!(visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)) return NULL; //g_message ("%s %s\n", G_STRFUNC, path); gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); /* allocate a new text entry widget to be used for editing */ /*text_renderer->entry = g_object_new (GTK_TYPE_ENTRY, "has-frame", FALSE, "text", text_renderer->text, "visible", TRUE, "xalign", xalign, NULL);*/ text_renderer->entry = eel_editable_label_new ("Test text"); eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (text_renderer->entry), TRUE); eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (text_renderer->entry), text_renderer->wrap_mode); eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (text_renderer->entry), TRUE); /* presume we're in POSITION UNDER */ if (text_renderer->wrap_width > 0) eel_editable_label_set_justify (EEL_EDITABLE_LABEL (text_renderer->entry), GTK_JUSTIFY_CENTER); //gtk_misc_set_alignment (GTK_MISC (text_renderer->entry), xalign, yalign); g_object_set (text_renderer->entry, "yalign", yalign, NULL); gtk_cell_renderer_get_padding (cell, &xpad, &ypad); gtk_misc_set_padding (GTK_MISC (text_renderer->entry), xpad, ypad); if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL) g_object_set (text_renderer->entry, "small-size", TRUE, NULL); gtk_widget_set_size_request (text_renderer->entry, text_renderer->wrap_width, -1); eel_editable_label_set_text (EEL_EDITABLE_LABEL (text_renderer->entry), text_renderer->text); gtk_widget_show (text_renderer->entry); /* remember the tree path that we're editing */ g_object_set_data_full (G_OBJECT (text_renderer->entry), "marlin-text-renderer-path", g_strdup (path), g_free); /* connect required signals */ g_signal_connect (G_OBJECT (text_renderer->entry), "editing-done", G_CALLBACK (marlin_text_renderer_editing_done), text_renderer); g_signal_connect (G_OBJECT (text_renderer->entry), "focus-out-event", G_CALLBACK (marlin_text_renderer_focus_out_event), text_renderer); g_signal_connect (G_OBJECT (text_renderer->entry), "populate-popup", G_CALLBACK (marlin_text_renderer_populate_popup), text_renderer); return GTK_CELL_EDITABLE (text_renderer->entry); }
static void marlin_text_renderer_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell); GtkStyleContext *context; GtkStateFlags state; gint x0, x1, y0, y1; gint text_width; gint text_height; gint x_offset; gint y_offset; gint xpad, ypad; gfloat xalign, yalign; gboolean selected; /* setup the new widget */ marlin_text_renderer_set_widget (text_renderer, widget); state = gtk_widget_get_state_flags (widget); if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) { state |= GTK_STATE_FLAG_SELECTED; } else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT && gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT) { state = GTK_STATE_PRELIGHT; } else { state = gtk_widget_get_sensitive (widget) ? GTK_STATE_FLAG_NORMAL : GTK_STATE_INSENSITIVE; } /* render small/normal text depending on the zoom_level */ if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL) { if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0) pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small_underline_single ()); else pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small ()); } else { if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0) pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_underline_single ()); else pango_layout_set_attributes (text_renderer->layout, NULL); } /* setup the wrapping */ if (text_renderer->wrap_width < 0) { pango_layout_set_width (text_renderer->layout, -1); pango_layout_set_wrap (text_renderer->layout, PANGO_WRAP_CHAR); } else { pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE); pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode); } /* ellipsize to max lines except for selected or prelit items */ pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END); pango_layout_set_height (text_renderer->layout, -3); if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED || (flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) { pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_NONE); } gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); if (xalign == 0.5f) pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER); pango_layout_set_text (text_renderer->layout, text_renderer->text, -1); /* calculate the real text dimension */ pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height); /* take into account the state indicator (required for calculation) */ if (text_renderer->follow_state) { text_width += 2 * text_renderer->focus_width; text_height += 2 * text_renderer->focus_width; } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); /* calculate the real x-offset */ x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); x_offset = MAX (x_offset, 0); /* calculate the real y-offset */ y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); y_offset = MAX (y_offset, 0); context = gtk_widget_get_style_context (gtk_widget_get_parent (widget)); gtk_style_context_save (context); gtk_style_context_set_state (context, state); selected = ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED && text_renderer->follow_state); /* render the state indicator */ if (selected || text_renderer->background != NULL) { /* calculate the text bounding box (including the focus padding/width) */ x0 = cell_area->x + x_offset; y0 = cell_area->y + y_offset; x1 = x0 + text_width; y1 = y0 + text_height; cairo_move_to (cr, x0 + 5, y0); cairo_line_to (cr, x1 - 5, y0); cairo_curve_to (cr, x1 - 5, y0, x1, y0, x1, y0 + 5); cairo_line_to (cr, x1, y1 - 5); cairo_curve_to (cr, x1, y1 - 5, x1, y1, x1 - 5, y1); cairo_line_to (cr, x0 + 5, y1); cairo_curve_to (cr, x0 + 5, y1, x0, y1, x0, y1 - 5); cairo_line_to (cr, x0, y0 + 5); cairo_curve_to (cr, x0, y0 + 5, x0, y0, x0 + 5, y0); GdkRGBA color; if(text_renderer->background != NULL && !selected) { if(!gdk_rgba_parse(&color, text_renderer->background)) { g_critical("Can't parse this color value: %s", text_renderer->background); gtk_style_context_get_background_color (context, state, &color); } } else { gtk_style_context_get_background_color (context, state, &color); } gdk_cairo_set_source_rgba (cr, &color); cairo_fill (cr); } /* draw the focus indicator */ if (text_renderer->follow_state && (flags & GTK_CELL_RENDERER_FOCUSED) != 0) { gtk_render_focus (context, cr, cell_area->x + x_offset, cell_area->y + y_offset, text_width, text_height); } /* get proper sizing for the layout drawing */ if (text_renderer->follow_state) { text_width -= 2 * text_renderer->focus_width; text_height -= 2 * text_renderer->focus_width; x_offset += text_renderer->focus_width; y_offset += text_renderer->focus_width; } /* draw the text */ if (xalign == 0.5f) x_offset = (cell_area->width - text_renderer->wrap_width)/2; gtk_render_layout (context, cr, cell_area->x + x_offset + xpad, cell_area->y + y_offset + ypad, text_renderer->layout); gtk_style_context_restore (context); }
static void marlin_text_renderer_get_size (GtkCellRenderer *cell, GtkWidget *widget, const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell); gint text_length; gint text_width; gint text_height; gint xpad, ypad; /* setup the new widget */ marlin_text_renderer_set_widget (text_renderer, widget); gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); /* we can guess the dimensions if we don't wrap */ if (text_renderer->wrap_width < 0) { /* determine the text_length in characters */ text_length = g_utf8_strlen (text_renderer->text, -1); /* the approximation is usually 1-2 chars wrong, so wth */ text_length += 2; /* calculate the appromixate text width/height */ text_width = text_renderer->char_width * text_length; text_height = text_renderer->char_height; } else { /* calculate the real text dimension */ pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END); pango_layout_set_height (text_renderer->layout, -3); pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE); pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode); pango_layout_set_text (text_renderer->layout, text_renderer->text, -1); if (xalign == 0.5f) pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER); pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height); } /* if we have to follow the state manually, we'll need * to reserve some space to render the indicator to. */ if (text_renderer->follow_state) { text_width += 2 * text_renderer->focus_width; text_height += 2 * text_renderer->focus_width; } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); /* update width/height */ if (G_LIKELY (width != NULL)) *width = text_width + 2 * xpad; if (G_LIKELY (height != NULL)) *height = text_height + 2 * ypad; /* update the x/y offsets */ if (G_LIKELY (cell_area != NULL)) { /*gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);*/ if (G_LIKELY (x_offset != NULL)) { *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); *x_offset = MAX (*x_offset, 0); } if (G_LIKELY (y_offset != NULL)) { *y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); *y_offset = MAX (*y_offset, 0); } } }
static void fm_cell_renderer_text_render(GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) #endif { FmCellRendererText *self = FM_CELL_RENDERER_TEXT(cell); #if GTK_CHECK_VERSION(3, 0, 0) GtkStyleContext* style; GtkStateFlags state; #else GtkStyle* style; GtkStateType state; #endif gchar* text; gint text_width; gint text_height; gint x_offset; gint y_offset; gint x_align_offset; GdkRectangle rect; PangoWrapMode wrap_mode; gint wrap_width; PangoAlignment alignment; gfloat xalign, yalign; gint xpad, ypad; /* FIXME: this is time-consuming since it invokes pango_layout. * if we want to fix this, we must implement the whole cell * renderer ourselves instead of derived from GtkCellRendererText. */ PangoContext* context = gtk_widget_get_pango_context(widget); PangoLayout* layout = pango_layout_new(context); g_object_get(G_OBJECT(cell), "wrap-mode" , &wrap_mode, "wrap-width", &wrap_width, "alignment" , &alignment, "text", &text, NULL); pango_layout_set_alignment(layout, alignment); /* Setup the wrapping. */ if (wrap_width < 0) { pango_layout_set_width(layout, -1); pango_layout_set_wrap(layout, PANGO_WRAP_CHAR); } else { pango_layout_set_width(layout, wrap_width * PANGO_SCALE); pango_layout_set_wrap(layout, wrap_mode); if(self->height > 0) { /* FIXME: add custom ellipsize from object? */ pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); pango_layout_set_height(layout, self->height * PANGO_SCALE); } else pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); } pango_layout_set_text(layout, text, -1); pango_layout_set_auto_dir(layout, TRUE); pango_layout_get_pixel_size(layout, &text_width, &text_height); gtk_cell_renderer_get_alignment(cell, &xalign, &yalign); gtk_cell_renderer_get_padding(cell, &xpad, &ypad); /* Calculate the real x and y offsets. */ x_offset = ((gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); x_offset = MAX(x_offset, 0); y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); y_offset = MAX (y_offset, 0); if(flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_FOCUSED)) { rect.x = cell_area->x + x_offset; rect.y = cell_area->y + y_offset; rect.width = text_width + (2 * xpad); rect.height = text_height + (2 * ypad); } #if GTK_CHECK_VERSION(3, 0, 0) style = gtk_widget_get_style_context(widget); #else style = gtk_widget_get_style(widget); #endif if(flags & GTK_CELL_RENDERER_SELECTED) /* item is selected */ { #if GTK_CHECK_VERSION(3, 0, 0) GdkRGBA clr; if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */ state = GTK_STATE_FLAG_INSENSITIVE; else state = GTK_STATE_FLAG_SELECTED; gtk_style_context_get_background_color(style, state, &clr); gdk_cairo_rectangle(cr, &rect); gdk_cairo_set_source_rgba(cr, &clr); #else cairo_t *cr = gdk_cairo_create (window); GdkColor clr; if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */ state = GTK_STATE_INSENSITIVE; else state = GTK_STATE_SELECTED; clr = style->bg[state]; /* paint the background */ if(expose_area) { gdk_cairo_rectangle(cr, expose_area); cairo_clip(cr); } gdk_cairo_rectangle(cr, &rect); cairo_set_source_rgb(cr, clr.red / 65535., clr.green / 65535., clr.blue / 65535.); #endif cairo_fill (cr); #if !GTK_CHECK_VERSION(3, 0, 0) cairo_destroy (cr); #endif } #if !GTK_CHECK_VERSION(3, 0, 0) else state = GTK_STATE_NORMAL; #endif x_align_offset = (alignment == PANGO_ALIGN_CENTER) ? (wrap_width - text_width) / 2 : 0; #if GTK_CHECK_VERSION(3, 0, 0) gtk_render_layout(style, cr, cell_area->x + x_offset + xpad - x_align_offset, cell_area->y + y_offset + ypad, layout); #else gtk_paint_layout(style, window, state, TRUE, expose_area, widget, "cellrenderertext", cell_area->x + x_offset + xpad - x_align_offset, cell_area->y + y_offset + ypad, layout); #endif g_object_unref(layout); if(G_UNLIKELY( flags & GTK_CELL_RENDERER_FOCUSED) ) /* focused */ { #if GTK_CHECK_VERSION(3, 0, 0) gtk_render_focus(style, cr, rect.x, rect.y, rect.width, rect.height); #else gtk_paint_focus(style, window, state, background_area, widget, "cellrenderertext", rect.x, rect.y, rect.width, rect.height); #endif } if(flags & GTK_CELL_RENDERER_PRELIT) /* hovered */ g_object_set(G_OBJECT(widget), "tooltip-text", text, NULL); else g_object_set(G_OBJECT(widget), "tooltip-text", NULL, NULL); g_free(text); }