[gnome-documents] two-lines: properly implement minimum/natural width request size
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] two-lines: properly implement minimum/natural width request size
- Date: Wed, 31 Aug 2011 19:55:32 +0000 (UTC)
commit 26b4d2d720260e744f074fe7df0362ce431e19f7
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Wed Aug 31 15:52:06 2011 -0400
two-lines: properly implement minimum/natural width request size
The code is mostly taken from GtkCellRendererText, and is needed to
appropriately ellipsize the cell renderer in list view with a
demaximized window without displaying any horizontal scrollbars.
src/lib/gd-two-lines-renderer.c | 173 +++++++++++++++++++++++++++++----------
1 files changed, 130 insertions(+), 43 deletions(-)
---
diff --git a/src/lib/gd-two-lines-renderer.c b/src/lib/gd-two-lines-renderer.c
index 58fafc2..b617f21 100644
--- a/src/lib/gd-two-lines-renderer.c
+++ b/src/lib/gd-two-lines-renderer.c
@@ -110,35 +110,59 @@ static void
gd_two_lines_renderer_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
- gint *height)
+ gint *height,
+ const GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset)
{
GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- gint layout_w, layout_h, total_w, total_h;
+ gint layout_w, layout_h;
gint xpad, ypad;
+ GdkRectangle layout_one_rect, layout_two_rect, layout_union;
gd_two_lines_renderer_prepare_layouts (self, widget);
+ gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
+
+ pango_layout_get_pixel_extents (self->priv->line_one_layout, NULL, (PangoRectangle *) &layout_one_rect);
+ pango_layout_get_pixel_extents (self->priv->line_one_layout, NULL, (PangoRectangle *) &layout_two_rect);
- pango_layout_get_pixel_size (self->priv->line_one_layout, &layout_w, &layout_h);
- total_w = layout_w;
- total_h = layout_h;
+ gdk_rectangle_union (&layout_one_rect, &layout_two_rect,
+ &layout_union);
- if (self->priv->line_two != NULL &&
- g_strcmp0 (self->priv->line_two, "") != 0)
+ if (cell_area)
{
- pango_layout_get_pixel_size (self->priv->line_two_layout, &layout_w, &layout_h);
- total_w = MAX (total_w, layout_w);
- total_h += layout_h;
+ gfloat xalign, yalign;
+
+ gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
+
+ layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad);
+ layout_union.width = MIN (layout_union.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 - (layout_union.width + (2 * xpad)));
+ else
+ *x_offset = xalign * (cell_area->width - (layout_union.width + (2 * xpad)));
+ *x_offset = MAX (*x_offset, 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) *x_offset = 0;
+ if (y_offset) *y_offset = 0;
}
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- total_w += 2 * xpad;
- total_h += 2 * ypad;
-
- if (width != NULL)
- *width = total_w;
+ if (height)
+ *height = ypad * 2 + layout_union.height;
- if (height != NULL)
- *height = total_h;
+ if (width)
+ *width = xpad * 2 + layout_union.width;
}
static void
@@ -154,15 +178,20 @@ gd_two_lines_renderer_render (GtkCellRenderer *cell,
gint line_one_height;
GtkStateFlags state;
GdkRectangle render_area = *cell_area;
- gint xpad, ypad;
+ gint xpad, ypad, x_offset, y_offset;
context = gtk_widget_get_style_context (widget);
- gd_two_lines_renderer_prepare_layouts (self, widget);
+ gd_two_lines_renderer_get_size (cell, widget,
+ NULL, NULL,
+ cell_area, &x_offset, &y_offset);
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- render_area.x += xpad;
+ render_area.x += xpad + x_offset;
render_area.y += ypad;
+ pango_layout_set_width (self->priv->line_one_layout,
+ (cell_area->width - x_offset - 2 * xpad) * PANGO_SCALE);
+
gtk_render_layout (context, cr,
render_area.x,
render_area.y,
@@ -195,32 +224,60 @@ gd_two_lines_renderer_get_preferred_width (GtkCellRenderer *cell,
gint *minimum_size,
gint *natural_size)
{
- gint width;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ const PangoFontDescription *font_desc;
+ GtkStyleContext *style_context;
+ gint nat_width, min_width;
+ gint xpad, char_width, wrap_width, text_width;
+ gint width_chars, ellipsize_chars;
+
+ g_object_get (cell,
+ "xpad", &xpad,
+ "width-chars", &width_chars,
+ "wrap-width", &wrap_width,
+ NULL);
+ style_context = gtk_widget_get_style_context (widget);
+ gtk_cell_renderer_get_padding (cell, &xpad, NULL);
- gd_two_lines_renderer_get_size (cell, widget, &width, NULL);
+ gd_two_lines_renderer_get_size (cell, widget,
+ &text_width, NULL,
+ NULL, NULL, NULL);
- if (minimum_size != NULL)
- *minimum_size = width;
+ /* Fetch the average size of a charachter */
+ context = gtk_widget_get_pango_context (widget);
+ font_desc = gtk_style_context_get_font (style_context, 0);
+ metrics = pango_context_get_metrics (context, font_desc,
+ pango_context_get_language (context));
- if (natural_size != NULL)
- *natural_size = width;
-}
+ char_width = pango_font_metrics_get_approximate_char_width (metrics);
-static void
-gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
-{
- gint height;
+ pango_font_metrics_unref (metrics);
- gd_two_lines_renderer_get_size (cell, widget, NULL, &height);
+ /* enforce minimum width for ellipsized labels at ~3 chars */
+ ellipsize_chars = 3;
- if (minimum_size != NULL)
- *minimum_size = height;
+ /* If no width-chars set, minimum for wrapping text will be the wrap-width */
+ if (wrap_width > -1)
+ min_width = xpad * 2 + MIN (text_width, wrap_width);
+ else
+ min_width = xpad * 2 +
+ MIN (text_width,
+ (PANGO_PIXELS (char_width) * MAX (width_chars, ellipsize_chars)));
- if (natural_size != NULL)
- *natural_size = height;
+ if (width_chars > 0)
+ nat_width = xpad * 2 +
+ MAX ((PANGO_PIXELS (char_width) * width_chars), text_width);
+ else
+ nat_width = xpad * 2 + text_width;
+
+ nat_width = MAX (nat_width, min_width);
+
+ if (minimum_size)
+ *minimum_size = min_width;
+
+ if (natural_size)
+ *natural_size = nat_width;
}
static void
@@ -230,7 +287,34 @@ gd_two_lines_renderer_get_preferred_height_for_width (GtkCellRenderer *cell,
gint *minimum_size,
gint *natural_size)
{
- gd_two_lines_renderer_get_preferred_height (cell, widget, minimum_size, natural_size);
+ gint text_height;
+ gint ypad;
+
+ gd_two_lines_renderer_get_size (cell, widget,
+ NULL, &text_height,
+ NULL, NULL, NULL);
+
+ gtk_cell_renderer_get_padding (cell, NULL, &ypad);
+ text_height += 2 * ypad;
+
+ if (minimum_size != NULL)
+ *minimum_size = text_height;
+
+ if (natural_size != NULL)
+ *natural_size = text_height;
+}
+
+static void
+gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ gint min_width;
+
+ gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL);
+ gd_two_lines_renderer_get_preferred_height_for_width (cell, widget, min_width,
+ minimum_size, natural_size);
}
static void
@@ -240,10 +324,13 @@ gd_two_lines_renderer_get_aligned_area (GtkCellRenderer *cell,
const GdkRectangle *cell_area,
GdkRectangle *aligned_area)
{
+ gint x_offset, y_offset;
+
gd_two_lines_renderer_get_size (cell, widget,
- &aligned_area->width, &aligned_area->height);
+ &aligned_area->width, &aligned_area->height,
+ cell_area, &x_offset, &y_offset);
- aligned_area->x = cell_area->x;
+ aligned_area->x = cell_area->x + x_offset;
aligned_area->y = cell_area->y;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]