aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table/e-table-header-utils.c
diff options
context:
space:
mode:
authorChris Toshok <toshok@ximian.com>2002-11-17 08:02:53 +0800
committerChris Toshok <toshok@src.gnome.org>2002-11-17 08:02:53 +0800
commit0bbe38655b71d4dd71277a1ecee246732f9fc2b1 (patch)
tree10655a0c2acb5f300986dfcfb90e5dbb3645d337 /widgets/table/e-table-header-utils.c
parentd8e4ebebc320c72ae93c88dc43d8ae220a94331d (diff)
downloadgsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar.gz
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar.bz2
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar.lz
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar.xz
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.tar.zst
gsoc2013-evolution-0bbe38655b71d4dd71277a1ecee246732f9fc2b1.zip
GObject port work.
2002-11-16 Chris Toshok <toshok@ximian.com> * e-cell-checkbox.[ch]: GObject port work. * e-cell-combo.[ch]: same. * e-cell-date.[ch]: same. * e-cell-float.[ch]: same. * e-cell-number.[ch]: same. * e-cell-pixbuf.[ch]: same. * e-cell-popup.[ch]: same. * e-cell-progress.[ch]: same. * e-cell-size.[ch]: same. * e-cell-spin-button.[ch]: same. * e-cell-text.[ch]: same. * e-cell-toggle.[ch]: same. * e-cell-tree.[ch]: same. * e-cell-vbox.[ch]: same. * e-cell.[ch]: same. * e-table-col.c: same. * e-table-column.c: same. * e-table-config-field.[ch]: same. * e-table-config.c: same. * e-table-config.glade: same. * e-table-field-chooser-dialog.[ch]: same. * e-table-field-chooser-item.[ch]: same. * e-table-field-chooser.[ch]: same. * e-table-group-container.[ch]: same. * e-table-group-leaf.[ch]: same. * e-table-group.[ch]: same. * e-table-header-item.[ch]: same. * e-table-header-utils.[ch]: same. * e-table-header.c: same. * e-table-item.[ch]: same. * e-table-scrolled.[ch]: same. * e-table-utils.c: same. * e-table.[ch]: same. * e-tree-memory-callbacks.h: same. * e-tree-scrolled.[ch]: same. * e-tree-sorted-variable.c: same. * e-tree.[ch]: same. * test-check.c: same. * test-cols.c: same. * test-table.c: same. svn path=/trunk/; revision=18801
Diffstat (limited to 'widgets/table/e-table-header-utils.c')
-rw-r--r--widgets/table/e-table-header-utils.c318
1 files changed, 185 insertions, 133 deletions
diff --git a/widgets/table/e-table-header-utils.c b/widgets/table/e-table-header-utils.c
index 60cc9f9e32..20c1529a23 100644
--- a/widgets/table/e-table-header-utils.c
+++ b/widgets/table/e-table-header-utils.c
@@ -38,32 +38,58 @@
+static PangoLayout*
+build_header_layout (GtkWidget *widget, const char *str)
+{
+ PangoLayout *layout;
+
+ layout = gtk_widget_create_pango_layout (widget, str);
+
+#ifdef FROB_FONT_DESC
+ {
+ PangoFontDescription *desc;
+ desc = pango_font_description_copy (gtk_widget_get_style (widget)->font_desc);
+ pango_font_description_set_size (desc,
+ pango_font_description_get_size (desc) * 1.2);
+
+ pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+ pango_layout_set_font_description (layout, desc);
+
+ pango_font_description_free (desc);
+ }
+#endif
+
+ return layout;
+}
+
/**
* e_table_header_compute_height:
* @ecol: Table column description.
- * @style: Style for the button's bevel.
- * @font: Font for the button's text, or NULL if no font is available.
+ * @widget: The widget from which to build the PangoLayout.
*
* Computes the minimum height required for a table header button.
*
* Return value: The height of the button, in pixels.
**/
double
-e_table_header_compute_height (ETableCol *ecol, GtkStyle *style, GdkFont *font)
+e_table_header_compute_height (ETableCol *ecol, GtkWidget *widget)
{
int ythick;
int height;
+ PangoLayout *layout;
+ PangoRectangle ink_rect;
g_return_val_if_fail (ecol != NULL, -1);
g_return_val_if_fail (E_IS_TABLE_COL (ecol), -1);
- g_return_val_if_fail (style != NULL, -1);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
- ythick = style->ythickness;
+ ythick = gtk_widget_get_style (widget)->ythickness;
- if (font)
- height = font->ascent + font->descent;
- else
- height = 16; /* FIXME: default? */
+ layout = build_header_layout (widget, ecol->text);
+
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+
+ height = PANGO_DESCENT (ink_rect) - PANGO_ASCENT (ink_rect);
if (ecol->is_pixbuf) {
g_assert (ecol->pixbuf != NULL);
@@ -74,6 +100,8 @@ e_table_header_compute_height (ETableCol *ecol, GtkStyle *style, GdkFont *font)
height += 2 * (ythick + HEADER_PADDING);
+ g_object_unref (layout);
+
return height;
}
@@ -196,6 +224,134 @@ make_composite_pixmap (GdkDrawable *drawable, GdkGC *gc,
return pixmap;
}
+
+/* Computes the length of a string that needs to be trimmed for elision */
+static int
+compute_elision_length (GtkWidget *widget, const char *str, int max_width)
+{
+ int len;
+ int l = 0, left, right;
+ PangoLayout *layout = build_header_layout (widget, str);
+ PangoRectangle ink_rect;
+
+ len = strlen (str);
+
+ if (len <= 0)
+ return 0;
+
+ left = 0;
+ right = len;
+
+ while (left < right) {
+ l = (left + right) / 2;
+
+ pango_layout_set_text (layout, str, l);
+
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+
+ if (PANGO_RBEARING (ink_rect) < max_width)
+ left = l + 1;
+ else if (PANGO_RBEARING (ink_rect) > max_width)
+ right = l;
+ else {
+ g_object_unref (layout);
+ return l;
+ }
+ }
+
+ g_object_unref (layout);
+
+ if (PANGO_RBEARING (ink_rect) > max_width)
+ return MAX (0, l - 1);
+ else
+ return l;
+
+ return l;
+}
+
+/* Default width of the elision arrow in pixels */
+#define ARROW_WIDTH 4
+
+/**
+ * e_table_draw_elided_string:
+ * @drawable: Destination drawable.
+ * @font: Font for the text.
+ * @gc: GC to use for drawing.
+ * @x: X insertion point for the string.
+ * @y: Y insertion point for the string's baseline.
+ * @str: String to draw.
+ * @max_width: Maximum width in which the string must fit.
+ * @center: Whether to center the string in the available area if it does fit.
+ *
+ * Draws a string, possibly trimming it so that it fits inside the specified
+ * maximum width. If it does not fit, an elision indicator is drawn after the
+ * last character that does fit.
+ **/
+static void
+e_table_draw_elided_string (GdkDrawable *drawable, GdkGC *gc, GtkWidget *widget,
+ int x, int y, const char *str, int max_width, gboolean center)
+{
+ PangoLayout *layout;
+ PangoRectangle ink_rect;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (str != NULL);
+ g_return_if_fail (max_width >= 0);
+
+ layout = build_header_layout (widget, str);
+
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+
+ if (PANGO_RBEARING (ink_rect) <= max_width) {
+ int xpos;
+
+ if (center)
+ xpos = x + (max_width - ink_rect.width) / 2;
+ else
+ xpos = x;
+
+ gdk_draw_layout (drawable, gc,
+ xpos, y,
+ layout);
+ } else {
+ int arrow_width;
+ int len;
+ int i;
+
+ if (max_width < ARROW_WIDTH + 1)
+ arrow_width = max_width - 1;
+ else
+ arrow_width = ARROW_WIDTH;
+
+ len = compute_elision_length (widget, str, max_width - arrow_width - 1);
+
+ pango_layout_set_text (layout, str, len);
+
+ gdk_draw_layout (drawable, gc,
+ x, y,
+ layout);
+
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+
+ y -= PANGO_ASCENT (ink_rect);
+
+ for (i = 0; i < arrow_width; i++) {
+ int h;
+
+ h = 2 * i + 1;
+
+ gdk_draw_line (drawable, gc,
+ x + PANGO_RBEARING(ink_rect) + arrow_width - i,
+ y + (PANGO_ASCENT (ink_rect) + PANGO_DESCENT (ink_rect) - h) / 2,
+ x + PANGO_RBEARING (ink_rect) + arrow_width - i,
+ y + (PANGO_ASCENT (ink_rect) + PANGO_DESCENT (ink_rect) - h) / 2 + h - 1);
+ }
+ }
+
+ g_object_unref (layout);
+}
+
static GtkWidget *g_label;
/**
@@ -203,7 +359,6 @@ static GtkWidget *g_label;
* @drawable: Destination drawable.
* @ecol: Table column for the header information.
* @style: Style to use for drawing the button.
- * @font: Font for the button's text.
* @state: State of the table widget.
* @widget: The table widget.
* @gc: GC to use for drawing.
@@ -219,7 +374,7 @@ static GtkWidget *g_label;
**/
void
e_table_header_draw_button (GdkDrawable *drawable, ETableCol *ecol,
- GtkStyle *style, GdkFont *font, GtkStateType state,
+ GtkStyle *style, GtkStateType state,
GtkWidget *widget,
int x, int y, int width, int height,
int button_width, int button_height,
@@ -235,7 +390,6 @@ e_table_header_draw_button (GdkDrawable *drawable, ETableCol *ecol,
g_return_if_fail (ecol != NULL);
g_return_if_fail (E_IS_TABLE_COL (ecol));
g_return_if_fail (style != NULL);
- g_return_if_fail (font != NULL);
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (button_width > 0 && button_height > 0);
@@ -307,8 +461,6 @@ e_table_header_draw_button (GdkDrawable *drawable, ETableCol *ecol,
/* Pixbuf or label */
- text = e_utf8_to_gtk_string (widget, ecol->text);
-
if (ecol->is_pixbuf) {
int pwidth, pheight;
int clip_width, clip_height;
@@ -326,20 +478,28 @@ e_table_header_draw_button (GdkDrawable *drawable, ETableCol *ecol,
xpos = inner_x;
if (inner_width - pwidth > 11) {
- int rbearing;
- int width;
+ PangoLayout *layout;
+ PangoRectangle ink_rect;
int ypos;
- gdk_string_extents (font, text, NULL, &rbearing, &width, NULL, NULL);
- if (rbearing < inner_width - (pwidth + 1)) {
- xpos = inner_x + (inner_width - width - (pwidth + 1)) / 2;
+ /* really sucks to generate another
+ PangoLayout here when we turn around and
+ make one in draw_elided_string */
+
+ layout = build_header_layout (widget, ecol->text);
+ pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
+
+ if (PANGO_RBEARING (ink_rect) < inner_width - (pwidth + 1)) {
+ xpos = inner_x + (inner_width - ink_rect.width - (pwidth + 1)) / 2;
}
- ypos = inner_y + (inner_height - font->ascent - font->descent) / 2 + font->ascent;
+ ypos = inner_y;
- e_table_draw_elided_string (drawable, font, gc,
+ e_table_draw_elided_string (drawable, gc, widget,
xpos + pwidth + 1, ypos,
- text, inner_width - (xpos - inner_x), FALSE);
+ ecol->text, inner_width - (xpos - inner_x), FALSE);
+
+ g_object_unref (layout);
}
pixmap = make_composite_pixmap (drawable, gc,
@@ -358,118 +518,10 @@ e_table_header_draw_button (GdkDrawable *drawable, ETableCol *ecol,
} else {
int ypos;
- ypos = inner_y + (inner_height - font->ascent - font->descent) / 2 + font->ascent;
+ ypos = inner_y;
- e_table_draw_elided_string (drawable, font, gc,
+ e_table_draw_elided_string (drawable, gc, widget,
inner_x, ypos,
- text, inner_width, TRUE);
- }
- g_free (text);
-}
-
-/* Computes the length of a string that needs to be trimmed for elision */
-static int
-compute_elision_length (GdkFont *font, const char *str, int max_width)
-{
- int len;
- int l = 0, left, right;
- int rbearing;
-
- len = strlen (str);
-
- if (len <= 0)
- return 0;
-
- left = 0;
- right = len;
-
- while (left < right) {
- l = (left + right) / 2;
- gdk_text_extents (font, str, l, NULL, &rbearing, NULL, NULL, NULL);
-
- if (rbearing < max_width)
- left = l + 1;
- else if (rbearing > max_width)
- right = l;
- else
- return l;
- }
-
- if (rbearing > max_width)
- return MAX (0, l - 1);
- else
- return l;
-}
-
-/* Default width of the elision arrow in pixels */
-#define ARROW_WIDTH 4
-
-/**
- * e_table_draw_elided_string:
- * @drawable: Destination drawable.
- * @font: Font for the text.
- * @gc: GC to use for drawing.
- * @x: X insertion point for the string.
- * @y: Y insertion point for the string's baseline.
- * @str: String to draw.
- * @max_width: Maximum width in which the string must fit.
- * @center: Whether to center the string in the available area if it does fit.
- *
- * Draws a string, possibly trimming it so that it fits inside the specified
- * maximum width. If it does not fit, an elision indicator is drawn after the
- * last character that does fit.
- **/
-void
-e_table_draw_elided_string (GdkDrawable *drawable, GdkFont *font, GdkGC *gc,
- int x, int y, const char *str, int max_width, gboolean center)
-{
- int rbearing;
- int width;
-
- g_return_if_fail (drawable != NULL);
- g_return_if_fail (font != NULL);
- g_return_if_fail (gc != NULL);
- g_return_if_fail (str != NULL);
- g_return_if_fail (max_width >= 0);
-
- gdk_string_extents (font, str, NULL, &rbearing, &width, NULL, NULL);
-
- if (rbearing <= max_width) {
- int xpos;
-
- if (center)
- xpos = x + (max_width - width) / 2;
- else
- xpos = x;
-
- gdk_draw_string (drawable, font, gc, xpos, y, str);
- } else {
- int arrow_width;
- int len;
- int i;
-
- if (max_width < ARROW_WIDTH + 1)
- arrow_width = max_width - 1;
- else
- arrow_width = ARROW_WIDTH;
-
- len = compute_elision_length (font, str, max_width - arrow_width - 1);
- gdk_draw_text (drawable, font, gc, x, y, str, len);
-
- gdk_text_extents (font, str, len, NULL, &rbearing, NULL, NULL, NULL);
-
- y -= font->ascent;
-
- for (i = 0; i < arrow_width; i++) {
- int h;
-
- h = 2 * i + 1;
-
- gdk_draw_line (drawable, gc,
- x + rbearing + arrow_width - i,
- y + (font->ascent + font->descent - h) / 2,
- x + rbearing + arrow_width - i,
- y + (font->ascent + font->descent - h) / 2 + h - 1);
- }
+ ecol->text, inner_width, TRUE);
}
}