aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-table-header-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'e-util/e-table-header-utils.c')
-rw-r--r--e-util/e-table-header-utils.c282
1 files changed, 282 insertions, 0 deletions
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);
+}