From d09d8de870b6697c8a8b262e7e077b871a69b315 Mon Sep 17 00:00:00 2001
From: Matthew Barnes <mbarnes@redhat.com>
Date: Mon, 10 Dec 2012 08:09:59 -0500
Subject: Consolidate base utility libraries into libeutil.

Evolution consists of entirely too many small utility libraries, which
increases linking and loading time, places a burden on higher layers of
the application (e.g. modules) which has to remember to link to all the
small in-tree utility libraries, and makes it difficult to generate API
documentation for these utility libraries in one Gtk-Doc module.

Merge the following utility libraries under the umbrella of libeutil,
and enforce a single-include policy on libeutil so we can reorganize
the files as desired without disrupting its pseudo-public API.

   libemail-utils/libemail-utils.la
   libevolution-utils/libevolution-utils.la
   filter/libfilter.la
   widgets/e-timezone-dialog/libetimezonedialog.la
   widgets/menus/libmenus.la
   widgets/misc/libemiscwidgets.la
   widgets/table/libetable.la
   widgets/text/libetext.la

This also merges libedataserverui from the Evolution-Data-Server module,
since Evolution is its only consumer nowadays, and I'd like to make some
improvements to those APIs without concern for backward-compatibility.

And finally, start a Gtk-Doc module for libeutil.  It's going to be a
project just getting all the symbols _listed_ much less _documented_.
But the skeletal structure is in place and I'm off to a good start.
---
 e-util/e-table-header-utils.c | 282 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 282 insertions(+)
 create mode 100644 e-util/e-table-header-utils.c

(limited to 'e-util/e-table-header-utils.c')

diff --git a/e-util/e-table-header-utils.c b/e-util/e-table-header-utils.c
new file mode 100644
index 0000000000..d3ee1aca38
--- /dev/null
+++ b/e-util/e-table-header-utils.c
@@ -0,0 +1,282 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *		Chris Lahey <clahey@ximian.com>
+ *      Miguel de Icaza <miguel@ximian.com>
+ *      Federico Mena-Quintero <federico@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-table-header-utils.h"
+
+#include <string.h> /* strlen() */
+
+#include <gtk/gtk.h>
+
+#include "e-table-defines.h"
+#include "e-unicode.h"
+
+static void
+get_button_padding (GtkWidget *widget,
+                    GtkBorder *padding)
+{
+	GtkStyleContext *context;
+	GtkStateFlags state_flags;
+
+	context = gtk_widget_get_style_context (widget);
+	state_flags = gtk_widget_get_state_flags (widget);
+
+	gtk_style_context_save (context);
+	gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
+	gtk_style_context_get_padding (context, state_flags, padding);
+
+	gtk_style_context_restore (context);
+}
+
+/**
+ * e_table_header_compute_height:
+ * @ecol: Table column description.
+ * @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.
+ **/
+gdouble
+e_table_header_compute_height (ETableCol *ecol,
+                               GtkWidget *widget)
+{
+	gint height;
+	PangoLayout *layout;
+	GtkBorder padding;
+
+	g_return_val_if_fail (ecol != NULL, -1);
+	g_return_val_if_fail (E_IS_TABLE_COL (ecol), -1);
+	g_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
+
+	get_button_padding (widget, &padding);
+
+	layout = gtk_widget_create_pango_layout (widget, ecol->text);
+
+	pango_layout_get_pixel_size (layout, NULL, &height);
+
+	if (ecol->icon_name != NULL) {
+		g_return_val_if_fail (ecol->pixbuf != NULL, -1);
+		height = MAX (height, gdk_pixbuf_get_height (ecol->pixbuf));
+	}
+
+	height = MAX (height, MIN_ARROW_SIZE);
+	height += padding.top + padding.bottom + 2 * HEADER_PADDING;
+
+	g_object_unref (layout);
+
+	return height;
+}
+
+gdouble
+e_table_header_width_extras (GtkWidget *widget)
+{
+	GtkBorder padding;
+
+	get_button_padding (widget, &padding);
+	return padding.left + padding.right + 2 * HEADER_PADDING;
+}
+
+/**
+ * e_table_header_draw_button:
+ * @drawable: Destination drawable.
+ * @ecol: Table column for the header information.
+ * @widget: The table widget.
+ * @x: Leftmost coordinate of the button.
+ * @y: Topmost coordinate of the button.
+ * @width: Width of the region to draw.
+ * @height: Height of the region to draw.
+ * @button_width: Width for the complete button.
+ * @button_height: Height for the complete button.
+ * @arrow: Arrow type to use as a sort indicator.
+ *
+ * Draws a button suitable for a table header.
+ **/
+void
+e_table_header_draw_button (cairo_t *cr,
+                            ETableCol *ecol,
+                            GtkWidget *widget,
+                            gint x,
+                            gint y,
+                            gint width,
+                            gint height,
+                            gint button_width,
+                            gint button_height,
+                            ETableColArrow arrow)
+{
+	gint inner_x, inner_y;
+	gint inner_width, inner_height;
+	gint arrow_width = 0, arrow_height = 0;
+	PangoContext *pango_context;
+	PangoLayout *layout;
+	GtkStyleContext *context;
+	GtkBorder padding;
+	GtkStateFlags state_flags;
+
+	g_return_if_fail (cr != NULL);
+	g_return_if_fail (ecol != NULL);
+	g_return_if_fail (E_IS_TABLE_COL (ecol));
+	g_return_if_fail (widget != NULL);
+	g_return_if_fail (GTK_IS_WIDGET (widget));
+	g_return_if_fail (button_width > 0 && button_height > 0);
+
+	/* Button bevel */
+	context = gtk_widget_get_style_context (widget);
+	state_flags = gtk_widget_get_state_flags (widget);
+
+	gtk_style_context_save (context);
+	gtk_style_context_set_state (context, state_flags);
+	gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
+
+	gtk_style_context_get_padding (context, state_flags, &padding);
+
+	gtk_render_background (
+		context, cr, x, y,
+		button_width, button_height);
+	gtk_render_frame (
+		context, cr, x, y,
+		button_width, button_height);
+
+	/* Inside area */
+
+	inner_width =
+		button_width -
+		(padding.left + padding.right + 2 * HEADER_PADDING);
+	inner_height =
+		button_height -
+		(padding.top + padding.bottom + 2 * HEADER_PADDING);
+
+	if (inner_width < 1 || inner_height < 1) {
+		return; /* nothing fits */
+	}
+
+	inner_x = x + padding.left + HEADER_PADDING;
+	inner_y = y + padding.top + HEADER_PADDING;
+
+	/* Arrow space */
+
+	switch (arrow) {
+	case E_TABLE_COL_ARROW_NONE:
+		break;
+
+	case E_TABLE_COL_ARROW_UP:
+	case E_TABLE_COL_ARROW_DOWN:
+		arrow_width = MIN (MIN_ARROW_SIZE, inner_width);
+		arrow_height = MIN (MIN_ARROW_SIZE, inner_height);
+
+		if (ecol->icon_name == NULL)
+			inner_width -= arrow_width + HEADER_PADDING;
+		break;
+	default:
+		cairo_restore (cr);
+		g_return_if_reached ();
+	}
+
+	if (inner_width < 1) {
+		gtk_style_context_restore (context);
+		return; /* nothing else fits */
+	}
+
+	pango_context = gtk_widget_create_pango_context (widget);
+	layout = pango_layout_new (pango_context);
+	g_object_unref (pango_context);
+
+	pango_layout_set_text (layout, ecol->text, -1);
+	pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+
+	/* Pixbuf or label */
+	if (ecol->icon_name != NULL) {
+		gint pwidth, pheight;
+		gint clip_height;
+		gint xpos;
+
+		g_return_if_fail (ecol->pixbuf != NULL);
+
+		pwidth = gdk_pixbuf_get_width (ecol->pixbuf);
+		pheight = gdk_pixbuf_get_height (ecol->pixbuf);
+
+		clip_height = MIN (pheight, inner_height);
+
+		xpos = inner_x;
+
+		if (inner_width - pwidth > 11) {
+			gint ypos;
+
+			pango_layout_get_pixel_size (layout, &width, NULL);
+
+			if (width < inner_width - (pwidth + 1)) {
+				xpos = inner_x + (inner_width - width - (pwidth + 1)) / 2;
+			}
+
+			ypos = inner_y;
+
+			pango_layout_set_width (
+				layout, (inner_width - (xpos - inner_x)) *
+				PANGO_SCALE);
+
+			gtk_render_layout (
+				context, cr, xpos + pwidth + 1,
+				ypos, layout);
+		}
+
+		gtk_render_icon (
+			context, cr, ecol->pixbuf, xpos,
+			inner_y + (inner_height - clip_height) / 2);
+
+	} else {
+		pango_layout_set_width (layout, inner_width * PANGO_SCALE);
+
+		gtk_render_layout (context, cr, inner_x, inner_y, layout);
+	}
+
+	switch (arrow) {
+	case E_TABLE_COL_ARROW_NONE:
+		break;
+
+	case E_TABLE_COL_ARROW_UP:
+	case E_TABLE_COL_ARROW_DOWN: {
+		if (ecol->icon_name == NULL)
+			inner_width += arrow_width + HEADER_PADDING;
+
+		gtk_render_arrow (
+			context, cr,
+			(arrow == E_TABLE_COL_ARROW_UP) ? 0 : G_PI,
+			inner_x + inner_width - arrow_width,
+			inner_y + (inner_height - arrow_height) / 2,
+			MAX (arrow_width, arrow_height));
+
+		break;
+	}
+
+	default:
+		cairo_restore (cr);
+		g_return_if_reached ();
+	}
+
+	g_object_unref (layout);
+	gtk_style_context_restore (context);
+}
-- 
cgit