X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcellrenderertext.c;h=3399bb2be0450e7f63164e1200b3fb9b4a7e9a00;hb=51be6b88dbff3ff6ed83d1247508ad58c0278df6;hp=5fd484a5ee4d0480be81b17482130d5fe9b265c9;hpb=af7a1879195bcdd443c6c1f2924df665d5a048f7;p=~andy%2Fgtk diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index 5fd484a5e..3399bb2be 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -12,21 +12,37 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" -#include + #include "gtkcellrenderertext.h" + +#include + #include "gtkeditable.h" -#include "gtkcellsizerequest.h" #include "gtkentry.h" +#include "gtksizerequest.h" #include "gtkmarshalers.h" #include "gtkintl.h" #include "gtkprivate.h" #include "gtktreeprivate.h" +#include "a11y/gtktextcellaccessible.h" + + +/** + * SECTION:gtkcellrenderertext + * @Short_description: Renders text in a cell + * @Title: GtkCellRendererText + * + * A #GtkCellRendererText renders a given text in its cell, using the font, color and + * style information provided by its properties. The text will be ellipsized if it is + * too long and the #GtkCellRendererText:ellipsize property allows it. + * + * If the #GtkCellRenderer:mode is %GTK_CELL_RENDERER_MODE_EDITABLE, + * the #GtkCellRendererText allows to edit its text using an entry. + */ static void gtk_cell_renderer_text_finalize (GObject *object); @@ -40,35 +56,40 @@ static void gtk_cell_renderer_text_set_property (GObject *obje const GValue *value, GParamSpec *pspec); static void gtk_cell_renderer_text_render (GtkCellRenderer *cell, - GdkWindow *window, + cairo_t *cr, GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags); static GtkCellEditable *gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags); -static void gtk_cell_renderer_text_cell_size_request_init (GtkCellSizeRequestIface *iface); -static void gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint *minimal_size, - gint *natural_size); -static void gtk_cell_renderer_text_get_height (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint *minimal_size, - gint *natural_size); -static void gtk_cell_renderer_text_get_height_for_width (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint width, - gint *minimum_height, - gint *natural_height); +static void gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell, + GtkWidget *widget, + gint *minimal_size, + gint *natural_size); +static void gtk_cell_renderer_text_get_preferred_height (GtkCellRenderer *cell, + GtkWidget *widget, + gint *minimal_size, + gint *natural_size); +static void gtk_cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer *cell, + GtkWidget *widget, + gint width, + gint *minimum_height, + gint *natural_height); +static void gtk_cell_renderer_text_get_aligned_area (GtkCellRenderer *cell, + GtkWidget *widget, + GtkCellRendererState flags, + const GdkRectangle *cell_area, + GdkRectangle *aligned_area); + + enum { EDITED, @@ -86,12 +107,15 @@ enum { PROP_MAX_WIDTH_CHARS, PROP_WRAP_WIDTH, PROP_ALIGN, - + PROP_PLACEHOLDER_TEXT, + /* Style args */ PROP_BACKGROUND, PROP_FOREGROUND, PROP_BACKGROUND_GDK, PROP_FOREGROUND_GDK, + PROP_BACKGROUND_RGBA, + PROP_FOREGROUND_RGBA, PROP_FONT, PROP_FONT_DESC, PROP_FAMILY, @@ -133,23 +157,22 @@ static guint text_cell_renderer_signals [LAST_SIGNAL]; #define GTK_CELL_RENDERER_TEXT_PATH "gtk-cell-renderer-text-path" -struct _GtkCellRendererTextPriv +struct _GtkCellRendererTextPrivate { GtkWidget *entry; - PangoAlignment align; PangoAttrList *extra_attrs; - PangoColor foreground; - PangoColor background; + GdkRGBA foreground; + GdkRGBA background; + PangoAlignment align; PangoEllipsizeMode ellipsize; PangoFontDescription *font; PangoLanguage *language; PangoUnderline underline_style; PangoWrapMode wrap_mode; - gboolean in_entry_menu; - gchar *text; + gchar *placeholder_text; gdouble font_scale; @@ -159,6 +182,7 @@ struct _GtkCellRendererTextPriv gint max_width_chars; gint wrap_width; + guint in_entry_menu : 1; guint strikethrough : 1; guint editable : 1; guint scale_set : 1; @@ -180,19 +204,17 @@ struct _GtkCellRendererTextPriv gulong entry_menu_popdown_timeout; }; -G_DEFINE_TYPE_WITH_CODE (GtkCellRendererText, gtk_cell_renderer_text, GTK_TYPE_CELL_RENDERER, - G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_SIZE_REQUEST, - gtk_cell_renderer_text_cell_size_request_init)) +G_DEFINE_TYPE (GtkCellRendererText, gtk_cell_renderer_text, GTK_TYPE_CELL_RENDERER) static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; GtkCellRenderer *cell = GTK_CELL_RENDERER (celltext); celltext->priv = G_TYPE_INSTANCE_GET_PRIVATE (celltext, GTK_TYPE_CELL_RENDERER_TEXT, - GtkCellRendererTextPriv); + GtkCellRendererTextPrivate); priv = celltext->priv; gtk_cell_renderer_set_alignment (cell, 0.0, 0.5); @@ -222,6 +244,10 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) cell_class->render = gtk_cell_renderer_text_render; cell_class->start_editing = gtk_cell_renderer_text_start_editing; + cell_class->get_preferred_width = gtk_cell_renderer_text_get_preferred_width; + cell_class->get_preferred_height = gtk_cell_renderer_text_get_preferred_height; + cell_class->get_preferred_height_for_width = gtk_cell_renderer_text_get_preferred_height_for_width; + cell_class->get_aligned_area = gtk_cell_renderer_text_get_aligned_area; g_object_class_install_property (object_class, PROP_TEXT, @@ -264,14 +290,35 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) NULL, GTK_PARAM_WRITABLE)); + /** + * GtkCellRendererText:background-gdk: + * + * Background color as a #GdkColor + * + * Deprecated: 3.4: Use #GtkCellRendererText:background-rgba instead. + */ g_object_class_install_property (object_class, PROP_BACKGROUND_GDK, g_param_spec_boxed ("background-gdk", P_("Background color"), P_("Background color as a GdkColor"), GDK_TYPE_COLOR, - GTK_PARAM_READWRITE)); + GTK_PARAM_READWRITE | G_PARAM_DEPRECATED)); + /** + * GtkCellRendererText:background-rgba: + * + * Background color as a #GdkRGBA + * + * Since: 3.0 + */ + g_object_class_install_property (object_class, + PROP_BACKGROUND_RGBA, + g_param_spec_boxed ("background-rgba", + P_("Background color as RGBA"), + P_("Background color as a GdkRGBA"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FOREGROUND, g_param_spec_string ("foreground", @@ -280,12 +327,34 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) NULL, GTK_PARAM_WRITABLE)); + /** + * GtkCellRendererText:foreground-gdk: + * + * Foreground color as a #GdkColor + * + * Deprecated: 3.4: Use #GtkCellRendererText:foreground-rgba instead. + */ g_object_class_install_property (object_class, PROP_FOREGROUND_GDK, g_param_spec_boxed ("foreground-gdk", P_("Foreground color"), P_("Foreground color as a GdkColor"), GDK_TYPE_COLOR, + GTK_PARAM_READWRITE | G_PARAM_DEPRECATED)); + + /** + * GtkCellRendererText:foreground-rgba: + * + * Foreground color as a #GdkRGBA + * + * Since: 3.0 + */ + g_object_class_install_property (object_class, + PROP_FOREGROUND_RGBA, + g_param_spec_boxed ("foreground-rgba", + P_("Foreground color as RGBA"), + P_("Foreground color as a GdkRGBA"), + GDK_TYPE_RGBA, GTK_PARAM_READWRITE)); @@ -552,7 +621,22 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) PANGO_TYPE_ALIGNMENT, PANGO_ALIGN_LEFT, GTK_PARAM_READWRITE)); - + + /** + * GtkCellRendererText:placeholder-text: + * + * The text that will be displayed in the #GtkCellRenderer if + * #GtkCellRendererText:editable is %TRUE and the cell is empty. + * + * Since 3.6 + */ + g_object_class_install_property (object_class, + PROP_PLACEHOLDER_TEXT, + g_param_spec_string ("placeholder-text", + P_("Placeholder text"), + P_("Text rendered when an editable cell is empty"), + NULL, + GTK_PARAM_READWRITE)); /* Style props are set or not */ @@ -624,7 +708,7 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) P_("Whether this tag affects the alignment mode")); /** - * GtkCellRendererText::edited + * GtkCellRendererText::edited: * @renderer: the object which received the signal * @path: the path identifying the edited cell * @new_text: the new text @@ -645,18 +729,21 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class) G_TYPE_STRING, G_TYPE_STRING); - g_type_class_add_private (object_class, sizeof (GtkCellRendererTextPriv)); + g_type_class_add_private (object_class, sizeof (GtkCellRendererTextPrivate)); + + gtk_cell_renderer_class_set_accessible_type (cell_class, GTK_TYPE_TEXT_CELL_ACCESSIBLE); } static void gtk_cell_renderer_text_finalize (GObject *object) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; pango_font_description_free (priv->font); g_free (priv->text); + g_free (priv->placeholder_text); if (priv->extra_attrs) pango_attr_list_unref (priv->extra_attrs); @@ -664,6 +751,8 @@ gtk_cell_renderer_text_finalize (GObject *object) if (priv->language) g_object_unref (priv->language); + g_clear_object (&priv->entry); + G_OBJECT_CLASS (gtk_cell_renderer_text_parent_class)->finalize (object); } @@ -696,7 +785,7 @@ gtk_cell_renderer_text_get_property (GObject *object, GParamSpec *pspec) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; switch (param_id) { @@ -715,11 +804,11 @@ gtk_cell_renderer_text_get_property (GObject *object, case PROP_BACKGROUND_GDK: { GdkColor color; - - color.red = priv->background.red; - color.green = priv->background.green; - color.blue = priv->background.blue; - + + color.red = (guint16) (priv->background.red * 65535); + color.green = (guint16) (priv->background.green * 65535); + color.blue = (guint16) (priv->background.blue * 65535); + g_value_set_boxed (value, &color); } break; @@ -727,15 +816,23 @@ gtk_cell_renderer_text_get_property (GObject *object, case PROP_FOREGROUND_GDK: { GdkColor color; - - color.red = priv->foreground.red; - color.green = priv->foreground.green; - color.blue = priv->foreground.blue; - + + color.red = (guint16) (priv->foreground.red * 65535); + color.green = (guint16) (priv->foreground.green * 65535); + color.blue = (guint16) (priv->foreground.blue * 65535); + g_value_set_boxed (value, &color); } break; + case PROP_BACKGROUND_RGBA: + g_value_set_boxed (value, &priv->background); + break; + + case PROP_FOREGROUND_RGBA: + g_value_set_boxed (value, &priv->foreground); + break; + case PROP_FONT: g_value_take_string (value, pango_font_description_to_string (priv->font)); break; @@ -873,6 +970,10 @@ gtk_cell_renderer_text_get_property (GObject *object, g_value_set_int (value, priv->max_width_chars); break; + case PROP_PLACEHOLDER_TEXT: + g_value_set_string (value, priv->placeholder_text); + break; + case PROP_BACKGROUND: case PROP_FOREGROUND: case PROP_MARKUP: @@ -885,21 +986,19 @@ gtk_cell_renderer_text_get_property (GObject *object, static void set_bg_color (GtkCellRendererText *celltext, - GdkColor *color) + GdkRGBA *rgba) { - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; - if (color) + if (rgba) { if (!priv->background_set) { priv->background_set = TRUE; g_object_notify (G_OBJECT (celltext), "background-set"); } - - priv->background.red = color->red; - priv->background.green = color->green; - priv->background.blue = color->blue; + + priv->background = *rgba; } else { @@ -914,21 +1013,19 @@ set_bg_color (GtkCellRendererText *celltext, static void set_fg_color (GtkCellRendererText *celltext, - GdkColor *color) + GdkRGBA *rgba) { - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; - if (color) + if (rgba) { if (!priv->foreground_set) { priv->foreground_set = TRUE; g_object_notify (G_OBJECT (celltext), "foreground-set"); } - - priv->foreground.red = color->red; - priv->foreground.green = color->green; - priv->foreground.blue = color->blue; + + priv->foreground = *rgba; } else { @@ -1020,7 +1117,7 @@ static void set_font_description (GtkCellRendererText *celltext, PangoFontDescription *font_desc) { - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; GObject *object = G_OBJECT (celltext); PangoFontDescription *new_font_desc; PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask; @@ -1072,7 +1169,7 @@ gtk_cell_renderer_text_set_property (GObject *object, GParamSpec *pspec) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object); - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; switch (param_id) { @@ -1138,12 +1235,12 @@ gtk_cell_renderer_text_set_property (GObject *object, case PROP_BACKGROUND: { - GdkColor color; + GdkRGBA rgba; if (!g_value_get_string (value)) set_bg_color (celltext, NULL); /* reset to background_set to FALSE */ - else if (gdk_color_parse (g_value_get_string (value), &color)) - set_bg_color (celltext, &color); + else if (gdk_rgba_parse (&rgba, g_value_get_string (value))) + set_bg_color (celltext, &rgba); else g_warning ("Don't know color `%s'", g_value_get_string (value)); @@ -1153,12 +1250,12 @@ gtk_cell_renderer_text_set_property (GObject *object, case PROP_FOREGROUND: { - GdkColor color; + GdkRGBA rgba; if (!g_value_get_string (value)) set_fg_color (celltext, NULL); /* reset to foreground_set to FALSE */ - else if (gdk_color_parse (g_value_get_string (value), &color)) - set_fg_color (celltext, &color); + else if (gdk_rgba_parse (&rgba, g_value_get_string (value))) + set_fg_color (celltext, &rgba); else g_warning ("Don't know color `%s'", g_value_get_string (value)); @@ -1167,11 +1264,57 @@ gtk_cell_renderer_text_set_property (GObject *object, break; case PROP_BACKGROUND_GDK: + { + GdkColor *color; + + color = g_value_get_boxed (value); + if (color) + { + GdkRGBA rgba; + + rgba.red = color->red / 65535.; + rgba.green = color->green / 65535.; + rgba.blue = color->blue / 65535.; + rgba.alpha = 1; + + set_bg_color (celltext, &rgba); + } + else + { + set_bg_color (celltext, NULL); + } + } + break; + + case PROP_FOREGROUND_GDK: + { + GdkColor *color; + + color = g_value_get_boxed (value); + if (color) + { + GdkRGBA rgba; + + rgba.red = color->red / 65535.; + rgba.green = color->green / 65535.; + rgba.blue = color->blue / 65535.; + rgba.alpha = 1; + + set_fg_color (celltext, &rgba); + } + else + { + set_fg_color (celltext, NULL); + } + } + break; + + case PROP_BACKGROUND_RGBA: /* This notifies the GObject itself. */ set_bg_color (celltext, g_value_get_boxed (value)); break; - case PROP_FOREGROUND_GDK: + case PROP_FOREGROUND_RGBA: /* This notifies the GObject itself. */ set_fg_color (celltext, g_value_get_boxed (value)); break; @@ -1391,7 +1534,12 @@ gtk_cell_renderer_text_set_property (GObject *object, case PROP_ALIGN_SET: priv->align_set = g_value_get_boolean (value); break; - + + case PROP_PLACEHOLDER_TEXT: + g_free (priv->placeholder_text); + priv->placeholder_text = g_value_dup_string (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -1417,6 +1565,15 @@ gtk_cell_renderer_text_new (void) return g_object_new (GTK_TYPE_CELL_RENDERER_TEXT, NULL); } +static inline gboolean +show_placeholder_text (GtkCellRendererText *celltext) +{ + GtkCellRendererTextPrivate *priv = celltext->priv; + + return priv->editable && priv->placeholder_text && + (!priv->text || !priv->text[0]); +} + static void add_attr (PangoAttrList *attr_list, PangoAttribute *attr) @@ -1430,16 +1587,18 @@ add_attr (PangoAttrList *attr_list, static PangoLayout* get_layout (GtkCellRendererText *celltext, GtkWidget *widget, - GdkRectangle *cell_area, + const GdkRectangle *cell_area, GtkCellRendererState flags) { - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; PangoAttrList *attr_list; PangoLayout *layout; PangoUnderline uline; gint xpad; + gboolean placeholder_layout = show_placeholder_text (celltext); - layout = gtk_widget_create_pango_layout (widget, priv->text); + layout = gtk_widget_create_pango_layout (widget, placeholder_layout ? + priv->placeholder_text : priv->text); gtk_cell_renderer_get_padding (GTK_CELL_RENDERER (celltext), &xpad, NULL); @@ -1450,7 +1609,7 @@ get_layout (GtkCellRendererText *celltext, pango_layout_set_single_paragraph_mode (layout, priv->single_paragraph); - if (cell_area) + if (!placeholder_layout && cell_area) { /* Add options that affect appearance but not size */ @@ -1463,8 +1622,10 @@ get_layout (GtkCellRendererText *celltext, { PangoColor color; - color = priv->foreground; - + color.red = (guint16) (priv->foreground.red * 65535); + color.green = (guint16) (priv->foreground.green * 65535); + color.blue = (guint16) (priv->foreground.blue * 65535); + add_attr (attr_list, pango_attr_foreground_new (color.red, color.green, color.blue)); } @@ -1473,6 +1634,22 @@ get_layout (GtkCellRendererText *celltext, add_attr (attr_list, pango_attr_strikethrough_new (priv->strikethrough)); } + else if (placeholder_layout) + { + PangoColor color; + GtkStyleContext *context; + GdkRGBA fg = { 0.5, 0.5, 0.5 }; + + context = gtk_widget_get_style_context (widget); + gtk_style_context_lookup_color (context, "placeholder_text_color", &fg); + + color.red = CLAMP (fg.red * 65535. + 0.5, 0, 65535); + color.green = CLAMP (fg.green * 65535. + 0.5, 0, 65535); + color.blue = CLAMP (fg.blue * 65535. + 0.5, 0, 65535); + + add_attr (attr_list, + pango_attr_foreground_new (color.red, color.green, color.blue)); + } add_attr (attr_list, pango_attr_font_desc_new (priv->font)); @@ -1564,17 +1741,17 @@ get_layout (GtkCellRendererText *celltext, static void -get_size (GtkCellRenderer *cell, - GtkWidget *widget, - GdkRectangle *cell_area, - PangoLayout *layout, - gint *x_offset, - gint *y_offset, - gint *width, - gint *height) +get_size (GtkCellRenderer *cell, + GtkWidget *widget, + const GdkRectangle *cell_area, + PangoLayout *layout, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell); - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; PangoRectangle rect; gint xpad, ypad; gint cell_width, cell_height; @@ -1583,12 +1760,17 @@ get_size (GtkCellRenderer *cell, if (priv->calc_fixed_height) { + GtkStyleContext *style_context; + GtkStateFlags state; PangoContext *context; PangoFontMetrics *metrics; PangoFontDescription *font_desc; gint row_height; - font_desc = pango_font_description_copy_static (widget->style->font_desc); + style_context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + + gtk_style_context_get (style_context, state, "font", &font_desc, NULL); pango_font_description_merge_static (font_desc, priv->font, TRUE); if (priv->scale_set) @@ -1629,44 +1811,21 @@ get_size (GtkCellRenderer *cell, pango_layout_get_pixel_extents (layout, NULL, &rect); - if (height) - *height = ypad * 2 + rect.height; - - /* The minimum size for ellipsized labels is ~ 3 chars */ - if (width) - { - if (priv->ellipsize || priv->width_chars > 0) - { - PangoContext *context; - PangoFontMetrics *metrics; - gint char_width; - - context = pango_layout_get_context (layout); - metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context)); - - char_width = pango_font_metrics_get_approximate_char_width (metrics); - pango_font_metrics_unref (metrics); - - *width = xpad * 2 + (PANGO_PIXELS (char_width) * MAX (priv->width_chars, 3)); - } - else - { - *width = xpad * 2 + rect.x + rect.width; - } - } - if (cell_area) { gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); + rect.height = MIN (rect.height, cell_area->height - 2 * ypad); + rect.width = MIN (rect.width, cell_area->width - 2 * xpad); + if (x_offset) { if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - *x_offset = (1.0 - xalign) * (cell_area->width - (rect.x + rect.width + (2 * xpad))); + *x_offset = (1.0 - xalign) * (cell_area->width - (rect.width + (2 * xpad))); else - *x_offset = xalign * (cell_area->width - (rect.x + rect.width + (2 * xpad))); + *x_offset = xalign * (cell_area->width - (rect.width + (2 * xpad))); if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->wrap_width != -1) *x_offset = MAX(*x_offset, 0); @@ -1683,93 +1842,66 @@ get_size (GtkCellRenderer *cell, if (y_offset) *y_offset = 0; } + if (height) + *height = ypad * 2 + rect.height; + + if (width) + *width = xpad * 2 + rect.width; + g_object_unref (layout); } static void gtk_cell_renderer_text_render (GtkCellRenderer *cell, - GdkDrawable *window, + cairo_t *cr, GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags) { GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell); - GtkCellRendererTextPriv *priv = celltext->priv; + GtkCellRendererTextPrivate *priv = celltext->priv; + GtkStyleContext *context; PangoLayout *layout; - GtkStateType state; gint x_offset = 0; gint y_offset = 0; gint xpad, ypad; + PangoRectangle rect; layout = get_layout (celltext, widget, cell_area, flags); get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, NULL, NULL); + context = gtk_widget_get_style_context (widget); - if (!gtk_cell_renderer_get_sensitive (cell)) - { - state = GTK_STATE_INSENSITIVE; - } - else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) - { - if (gtk_widget_has_focus (widget)) - state = GTK_STATE_SELECTED; - else - state = GTK_STATE_ACTIVE; - } - else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT && - gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT) - { - state = GTK_STATE_PRELIGHT; - } - else - { - if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE) - state = GTK_STATE_INSENSITIVE; - else - state = GTK_STATE_NORMAL; - } - - if (priv->background_set && - (flags & GTK_CELL_RENDERER_SELECTED) == 0) + if (priv->background_set && (flags & GTK_CELL_RENDERER_SELECTED) == 0) { - cairo_t *cr = gdk_cairo_create (window); - - if (expose_area) - { - gdk_cairo_rectangle (cr, expose_area); - cairo_clip (cr); - } - gdk_cairo_rectangle (cr, background_area); - cairo_set_source_rgb (cr, - priv->background.red / 65535., - priv->background.green / 65535., - priv->background.blue / 65535.); + gdk_cairo_set_source_rgba (cr, &priv->background); cairo_fill (cr); - - cairo_destroy (cr); } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); if (priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) - pango_layout_set_width (layout, + pango_layout_set_width (layout, (cell_area->width - x_offset - 2 * xpad) * PANGO_SCALE); else if (priv->wrap_width == -1) pango_layout_set_width (layout, -1); - gtk_paint_layout (widget->style, - window, - state, - TRUE, - expose_area, - widget, - "cellrenderertext", - cell_area->x + x_offset + xpad, - cell_area->y + y_offset + ypad, - layout); + pango_layout_get_pixel_extents (layout, NULL, &rect); + x_offset = x_offset - rect.x; + + cairo_save (cr); + + gdk_cairo_rectangle (cr, cell_area); + cairo_clip (cr); + + gtk_render_layout (context, cr, + cell_area->x + x_offset + xpad, + cell_area->y + y_offset + ypad, + layout); + + cairo_restore (cr); g_object_unref (layout); } @@ -1778,14 +1910,14 @@ static void gtk_cell_renderer_text_editing_done (GtkCellEditable *entry, gpointer data) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; const gchar *path; const gchar *new_text; gboolean canceled; priv = GTK_CELL_RENDERER_TEXT (data)->priv; - priv->entry = NULL; + g_clear_object (&priv->entry); if (priv->focus_out_id > 0) { @@ -1822,7 +1954,7 @@ gtk_cell_renderer_text_editing_done (GtkCellEditable *entry, static gboolean popdown_timeout (gpointer data) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; priv = GTK_CELL_RENDERER_TEXT (data)->priv; @@ -1838,7 +1970,7 @@ static void gtk_cell_renderer_text_popup_unmap (GtkMenu *menu, gpointer data) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; priv = GTK_CELL_RENDERER_TEXT (data)->priv; @@ -1856,7 +1988,7 @@ gtk_cell_renderer_text_populate_popup (GtkEntry *entry, GtkMenu *menu, gpointer data) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; priv = GTK_CELL_RENDERER_TEXT (data)->priv; @@ -1877,7 +2009,7 @@ gtk_cell_renderer_text_focus_out_event (GtkWidget *entry, GdkEvent *event, gpointer data) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; priv = GTK_CELL_RENDERER_TEXT (data)->priv; @@ -1899,13 +2031,12 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags) { - GtkRequisition requisition; GtkCellRendererText *celltext; - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; gfloat xalign, yalign; celltext = GTK_CELL_RENDERER_TEXT (cell); @@ -1918,6 +2049,8 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); priv->entry = gtk_entry_new (); + g_object_ref_sink (G_OBJECT (priv->entry)); + gtk_entry_set_has_frame (GTK_ENTRY (priv->entry), FALSE); gtk_entry_set_alignment (GTK_ENTRY (priv->entry), xalign); @@ -1926,33 +2059,6 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, g_object_set_data_full (G_OBJECT (priv->entry), I_(GTK_CELL_RENDERER_TEXT_PATH), g_strdup (path), g_free); gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1); - - gtk_widget_size_request (priv->entry, &requisition); - if (requisition.height < cell_area->height) - { - GtkBorder *style_border; - GtkBorder border; - - gtk_widget_style_get (priv->entry, - "inner-border", &style_border, - NULL); - - if (style_border) - { - border = *style_border; - g_boxed_free (GTK_TYPE_BORDER, style_border); - } - else - { - /* Since boxed style properties can't have default values ... */ - border.left = 2; - border.right = 2; - } - - border.top = (cell_area->height - requisition.height) / 2; - border.bottom = (cell_area->height - requisition.height) / 2; - gtk_entry_set_inner_border (GTK_ENTRY (priv->entry), &border); - } priv->in_entry_menu = FALSE; if (priv->entry_menu_popdown_timeout) @@ -1995,7 +2101,7 @@ void gtk_cell_renderer_text_set_fixed_height_from_font (GtkCellRendererText *renderer, gint number_of_rows) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; GtkCellRenderer *cell; g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer)); @@ -2019,26 +2125,18 @@ gtk_cell_renderer_text_set_fixed_height_from_font (GtkCellRendererText *renderer } static void -gtk_cell_renderer_text_cell_size_request_init (GtkCellSizeRequestIface *iface) -{ - iface->get_width = gtk_cell_renderer_text_get_width; - iface->get_height = gtk_cell_renderer_text_get_height; - iface->get_height_for_width = gtk_cell_renderer_text_get_height_for_width; -} - -static void -gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint *minimum_size, - gint *natural_size) +gtk_cell_renderer_text_get_preferred_width (GtkCellRenderer *cell, + GtkWidget *widget, + gint *minimum_size, + gint *natural_size) { - GtkCellRendererTextPriv *priv; + GtkCellRendererTextPrivate *priv; GtkCellRendererText *celltext; PangoLayout *layout; PangoContext *context; PangoFontMetrics *metrics; PangoRectangle rect; - gint char_width, digit_width, char_pixels, text_width, ellipsize_chars, guess_width, xpad; + gint char_width, text_width, ellipsize_chars, xpad; gint min_width, nat_width; /* "width-chars" Hard-coded minimum width: @@ -2053,14 +2151,10 @@ gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, celltext = GTK_CELL_RENDERER_TEXT (cell); priv = celltext->priv; - gtk_cell_renderer_get_padding (GTK_CELL_RENDERER (cell), &xpad, NULL); + gtk_cell_renderer_get_padding (cell, &xpad, NULL); layout = get_layout (celltext, widget, NULL, 0); - /* Get the layout with the text possibly wrapping at wrap_width */ - pango_layout_get_pixel_extents (layout, NULL, &rect); - guess_width = rect.width; - /* Fetch the length of the complete unwrapped text */ pango_layout_set_width (layout, -1); pango_layout_get_extents (layout, NULL, &rect); @@ -2068,12 +2162,11 @@ gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, /* Fetch the average size of a charachter */ context = pango_layout_get_context (layout); - metrics = pango_context_get_metrics (context, widget->style->font_desc, - pango_context_get_language (context)); - + metrics = pango_context_get_metrics (context, + pango_context_get_font_description (context), + pango_context_get_language (context)); + char_width = pango_font_metrics_get_approximate_char_width (metrics); - digit_width = pango_font_metrics_get_approximate_digit_width (metrics); - char_pixels = MAX (char_width, digit_width); pango_font_metrics_unref (metrics); g_object_unref (layout); @@ -2083,24 +2176,25 @@ gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, ellipsize_chars = 3; else ellipsize_chars = 0; - + if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->width_chars > 0) - min_width = - xpad * 2 + (PANGO_PIXELS (char_width) * MAX (priv->width_chars, ellipsize_chars)); + min_width = xpad * 2 + + MIN (PANGO_PIXELS_CEIL (text_width), + (PANGO_PIXELS (char_width) * MAX (priv->width_chars, ellipsize_chars))); /* If no width-chars set, minimum for wrapping text will be the wrap-width */ else if (priv->wrap_width > -1) - min_width = xpad * 2 + rect.x + priv->wrap_width; + min_width = xpad * 2 + rect.x + MIN (PANGO_PIXELS_CEIL (text_width), priv->wrap_width); else - min_width = xpad * 2 + rect.x + guess_width; + min_width = xpad * 2 + rect.x + PANGO_PIXELS_CEIL (text_width); if (priv->width_chars > 0) - nat_width = xpad * 2 + - MAX ((PANGO_PIXELS (char_width) * priv->width_chars), PANGO_PIXELS (text_width)); + nat_width = xpad * 2 + + MAX ((PANGO_PIXELS (char_width) * priv->width_chars), PANGO_PIXELS_CEIL (text_width)); else - nat_width = xpad * 2 + PANGO_PIXELS (text_width); + nat_width = xpad * 2 + PANGO_PIXELS_CEIL (text_width); nat_width = MAX (nat_width, min_width); - + if (priv->max_width_chars > 0) { gint max_width = xpad * 2 + PANGO_PIXELS (char_width) * priv->max_width_chars; @@ -2114,28 +2208,25 @@ gtk_cell_renderer_text_get_width (GtkCellSizeRequest *cell, if (natural_size) *natural_size = nat_width; - } static void -gtk_cell_renderer_text_get_height_for_width (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint width, - gint *minimum_height, - gint *natural_height) +gtk_cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer *cell, + GtkWidget *widget, + gint width, + gint *minimum_height, + gint *natural_height) { - GtkCellRendererTextPriv *priv; - GtkCellRendererText *celltext; - PangoLayout *layout; - gint text_height, xpad, ypad; + GtkCellRendererText *celltext; + PangoLayout *layout; + gint text_height, xpad, ypad; celltext = GTK_CELL_RENDERER_TEXT (cell); - priv = celltext->priv; - gtk_cell_renderer_get_padding (GTK_CELL_RENDERER (cell), &xpad, &ypad); + gtk_cell_renderer_get_padding (cell, &xpad, &ypad); - layout = get_layout (celltext, widget, FALSE, 0); + layout = get_layout (celltext, widget, NULL, 0); pango_layout_set_width (layout, (width - xpad * 2) * PANGO_SCALE); pango_layout_get_pixel_size (layout, NULL, &text_height); @@ -2150,10 +2241,10 @@ gtk_cell_renderer_text_get_height_for_width (GtkCellSizeRequest *cell, } static void -gtk_cell_renderer_text_get_height (GtkCellSizeRequest *cell, - GtkWidget *widget, - gint *minimum_size, - gint *natural_size) +gtk_cell_renderer_text_get_preferred_height (GtkCellRenderer *cell, + GtkWidget *widget, + gint *minimum_size, + gint *natural_size) { gint min_width; @@ -2164,8 +2255,29 @@ gtk_cell_renderer_text_get_height (GtkCellSizeRequest *cell, * Note this code path wont be followed by GtkTreeView which is * height-for-width specifically. */ - gtk_cell_size_request_get_width (cell, widget, &min_width, NULL); - gtk_cell_renderer_text_get_height_for_width (cell, widget, min_width, - minimum_size, natural_size); + gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL); + gtk_cell_renderer_text_get_preferred_height_for_width (cell, widget, min_width, + minimum_size, natural_size); } +static void +gtk_cell_renderer_text_get_aligned_area (GtkCellRenderer *cell, + GtkWidget *widget, + GtkCellRendererState flags, + const GdkRectangle *cell_area, + GdkRectangle *aligned_area) +{ + GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell); + PangoLayout *layout; + gint x_offset = 0; + gint y_offset = 0; + + layout = get_layout (celltext, widget, cell_area, flags); + get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, + &aligned_area->width, &aligned_area->height); + + aligned_area->x = cell_area->x + x_offset; + aligned_area->y = cell_area->y + y_offset; + + g_object_unref (layout); +}