diff options
author | Christopher James Lahey <clahey@helixcode.com> | 2000-03-06 07:15:14 +0800 |
---|---|---|
committer | Chris Lahey <clahey@src.gnome.org> | 2000-03-06 07:15:14 +0800 |
commit | 3de981ec78d529eb1bd9b2f98f154eae91dffc6d (patch) | |
tree | e8758124523b6c534890aa80f5b918981be6ce00 /widgets | |
parent | 645f69dcf6d0b6162c5c7843371c559486234175 (diff) | |
download | gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.gz gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.bz2 gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.lz gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.xz gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.tar.zst gsoc2013-evolution-3de981ec78d529eb1bd9b2f98f154eae91dffc6d.zip |
Added support for the sorting info. The Etable creates a sort_info object,
2000-03-05 Christopher James Lahey <clahey@helixcode.com>
* e-table.c, e-table.h: Added support for the sorting info. The
Etable creates a sort_info object, and then connects to the
signals to rearrange the rows when the sort_info changes. It also
passes the info object to the ETableHeaderItem.
* e-table-model.c: Fixed a typo where ETableModel was written as
ETableModle.
* e-table-header.c, e-table-header.h: Added some code for sorting
here, but it's not used. I don't think we want this code, but I
wanted to check it in at least once so that it's not lost.
* e-table-header-item.c, e-table-header-item.h: Added a
"sort_info" argument to ETableHeaderItem. Added display of
current sort settings. Added support for clicking to change the
sort settings.
* e-table-col.h: E_TABLE_COL_ARROW_NONE is marked as being = 0
since this is required in other places. (I think C defines this
as being the case, but it's good to have the = 0 there so that
it's obvious that it has to be first.)
* TODO: Mark sorting as done.
* e-table-sort-info.c, e-table-sort-info.h: New files for
containing the xml grouping/sorting information and for sending
signals on that information.
* Makefile.am: Added e-table-sort-info.c and e-table-sort-info.h.
svn path=/trunk/; revision=2060
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/e-table/ChangeLog | 32 | ||||
-rw-r--r-- | widgets/e-table/Makefile.am | 2 | ||||
-rw-r--r-- | widgets/e-table/TODO | 13 | ||||
-rw-r--r-- | widgets/e-table/e-table-col.h | 2 | ||||
-rw-r--r-- | widgets/e-table/e-table-header-item.c | 109 | ||||
-rw-r--r-- | widgets/e-table/e-table-header-item.h | 8 | ||||
-rw-r--r-- | widgets/e-table/e-table-header.c | 131 | ||||
-rw-r--r-- | widgets/e-table/e-table-header.h | 27 | ||||
-rw-r--r-- | widgets/e-table/e-table-model.c | 2 | ||||
-rw-r--r-- | widgets/e-table/e-table-sort-info.c | 124 | ||||
-rw-r--r-- | widgets/e-table/e-table-sort-info.h | 37 | ||||
-rw-r--r-- | widgets/e-table/e-table.c | 40 | ||||
-rw-r--r-- | widgets/e-table/e-table.h | 5 | ||||
-rw-r--r-- | widgets/table/e-table-col.h | 2 | ||||
-rw-r--r-- | widgets/table/e-table-header-item.c | 109 | ||||
-rw-r--r-- | widgets/table/e-table-header-item.h | 8 | ||||
-rw-r--r-- | widgets/table/e-table-header.c | 131 | ||||
-rw-r--r-- | widgets/table/e-table-header.h | 27 | ||||
-rw-r--r-- | widgets/table/e-table-model.c | 2 | ||||
-rw-r--r-- | widgets/table/e-table-sort-info.c | 124 | ||||
-rw-r--r-- | widgets/table/e-table-sort-info.h | 37 | ||||
-rw-r--r-- | widgets/table/e-table.c | 40 | ||||
-rw-r--r-- | widgets/table/e-table.h | 5 |
23 files changed, 992 insertions, 25 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index be5b2fad0a..9a074a3e8b 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,35 @@ +2000-03-05 Christopher James Lahey <clahey@helixcode.com> + + * e-table.c, e-table.h: Added support for the sorting info. The + Etable creates a sort_info object, and then connects to the + signals to rearrange the rows when the sort_info changes. It also + passes the info object to the ETableHeaderItem. + + * e-table-model.c: Fixed a typo where ETableModel was written as + ETableModle. + + * e-table-header.c, e-table-header.h: Added some code for sorting + here, but it's not used. I don't think we want this code, but I + wanted to check it in at least once so that it's not lost. + + * e-table-header-item.c, e-table-header-item.h: Added a + "sort_info" argument to ETableHeaderItem. Added display of + current sort settings. Added support for clicking to change the + sort settings. + + * e-table-col.h: E_TABLE_COL_ARROW_NONE is marked as being = 0 + since this is required in other places. (I think C defines this + as being the case, but it's good to have the = 0 there so that + it's obvious that it has to be first.) + + * TODO: Mark sorting as done. + + * e-table-sort-info.c, e-table-sort-info.h: New files for + containing the xml grouping/sorting information and for sending + signals on that information. + + * Makefile.am: Added e-table-sort-info.c and e-table-sort-info.h. + 2000-03-04 Christopher James Lahey <clahey@helixcode.com> * e-table.c: Added saving of frozen_columns count. Added a diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index d32b74d406..3619c6bef3 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -37,6 +37,8 @@ libetable_a_SOURCES = \ e-table-model.h \ e-table-simple.c \ e-table-simple.h \ + e-table-sort-info.c \ + e-table-sort-info.h \ e-table-sorted.c \ e-table-sorted.h \ e-table-sorted-variable.c \ diff --git a/widgets/e-table/TODO b/widgets/e-table/TODO index bbad34e6ef..35ba2eb6b9 100644 --- a/widgets/e-table/TODO +++ b/widgets/e-table/TODO @@ -30,12 +30,11 @@ mouse grabbing for scrolling + * Add frozen_columns output. * Add input and output of column widths and minimum column widths. -* Add GUI sort ++ * Add GUI sort - * Add a method to the ETableGroup class to change the sorting information. - * Add a way to get sorting information out of the ETableHeader. - * Add display of proper arrows to the ETableHeaderItem. - * Add switching of sorting on clicks. ++ * Create an ETableSortInfo class. ++ * Add display of proper arrows to the ETableHeaderItem. ++ * Add switching of sorting on clicks. * Add depressed button state to ETableHeaderItem? * Add GUI grouping @@ -71,4 +70,8 @@ mouse grabbing for scrolling * Implement ETableDataEntry (a subclass of ETableModel). * Build GUI for the data entry model. This should be fairly simple. +* Draw little arrows for new column position instead of little triangles. +* Make new column position be closest to position instead of rounding to the left. +* Copy gtk_dnd as e_dnd. + * Fix known bug about navigating out of the bottom of the table. diff --git a/widgets/e-table/e-table-col.h b/widgets/e-table/e-table-col.h index c6f9c9dfb5..816879792e 100644 --- a/widgets/e-table/e-table-col.h +++ b/widgets/e-table/e-table-col.h @@ -16,7 +16,7 @@ typedef struct _ETableColClass ETableColClass; typedef enum _ETableColArrow ETableColArrow; enum _ETableColArrow { - E_TABLE_COL_ARROW_NONE, + E_TABLE_COL_ARROW_NONE = 0, E_TABLE_COL_ARROW_UP, E_TABLE_COL_ARROW_DOWN }; diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index 475e15c31d..82637a8a82 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -16,6 +16,7 @@ #include <libgnomeui/gnome-canvas-rect-ellipse.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include "e-util/e-cursors.h" +#include "e-util/e-xml-utils.h" #include "e-table-header.h" #include "e-table-header-item.h" #include "e-table-col-dnd.h" @@ -55,7 +56,8 @@ enum { ARG_TABLE_HEADER, ARG_TABLE_X, ARG_TABLE_Y, - ARG_TABLE_FONTSET + ARG_TABLE_FONTSET, + ARG_SORT_INFO }; static GtkTargetEntry ethi_drag_types [] = { @@ -71,6 +73,8 @@ ethi_destroy (GtkObject *object){ ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object); ethi_drop_table_header (ethi); + if ( ethi->sort_info ) + gtk_object_unref(GTK_OBJECT(ethi->sort_info)); if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object); @@ -181,6 +185,11 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) case ARG_TABLE_FONTSET: ethi_font_load (ethi, GTK_VALUE_STRING (*arg)); break; + + case ARG_SORT_INFO: + ethi->sort_info = GTK_VALUE_POINTER (*arg); + gtk_object_ref(GTK_OBJECT(ethi->sort_info)); + break; } ethi_update (item, NULL, NULL, 0); @@ -482,7 +491,7 @@ ethi_unrealize (GnomeCanvasItem *item) static void draw_button (ETableHeaderItem *ethi, ETableCol *col, GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height) + int x, int y, int width, int height, ETableColArrow arrow) { GdkRectangle clip; int xtra; @@ -532,7 +541,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, col->text, strlen (col->text)); } - switch ( e_table_col_get_arrow(col) ) { + switch ( arrow ) { case E_TABLE_COL_ARROW_NONE: break; case E_TABLE_COL_ARROW_UP: @@ -544,7 +553,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, &clip, GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas), "header", - e_table_col_get_arrow(col) == E_TABLE_COL_ARROW_UP ? GTK_ARROW_UP : GTK_ARROW_DOWN, + (arrow == E_TABLE_COL_ARROW_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, TRUE, x + PADDING / 2 + clip.width - MIN_ARROW_SIZE - 2, y + (ethi->height - MIN_ARROW_SIZE) / 2, @@ -563,11 +572,34 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width const int cols = e_table_header_count (ethi->eth); int x1, x2; int col; + GHashTable *arrows = g_hash_table_new(NULL, NULL); + xmlNode *node; #if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); #endif + + if (ethi->sort_info) { + xmlNode *grouping; + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + for (node = grouping->childs; node && strcmp(node->name, "leaf"); node = node->childs) { + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + if ( node ) + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + x1 = x2 = ethi->x1; for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); @@ -590,8 +622,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x1 - x, ethi->y1 - y, col_width, ethi->height); + x1 - x, ethi->y1 - y, col_width, ethi->height, + (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) ); } + g_hash_table_destroy(arrows); } static double @@ -698,6 +732,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) int col_width; GdkPixmap *pixmap; GdkGC *gc; + GHashTable *arrows = g_hash_table_new(NULL, NULL); + xmlNode *node; ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); if ( ethi->drag_col < ethi->eth->frozen_count && ethi->drag_col >= 0 ) { @@ -707,6 +743,27 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) if (ethi->drag_col == -1) return; + + if (ethi->sort_info) { + xmlNode *grouping; + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + for (node = grouping->childs; node && strcmp(node->name, "leaf"); node = node->childs) { + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + if ( node ) + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); @@ -719,7 +776,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) gc = widget->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, pixmap, gc, widget->style, - 0, 0, col_width, ethi->height); + 0, 0, col_width, ethi->height, + (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) ); gtk_drag_set_icon_pixmap (context, gdk_window_get_colormap(widget->window), pixmap, @@ -729,6 +787,7 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) gdk_pixmap_unref(pixmap); ethi->maybe_drag = FALSE; + g_hash_table_destroy(arrows); } /* @@ -830,6 +889,40 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (ethi->resize_col != -1){ needs_ungrab = (ethi->resize_guide != NULL); ethi_end_resize (ethi, ethi->resize_width); + } else if (ethi->maybe_drag && ethi->sort_info) { + ETableCol *col; + int model_col; + xmlNode *node; + xmlNode *grouping; + + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + + col = e_table_header_get_column(ethi->eth, ethi_find_col_by_x (ethi, e->button.x)); + model_col = col->col_idx; + for (node = grouping->childs; node->childs && strcmp(node->name, "leaf"); node = node->childs) { + if ( model_col == e_xml_get_integer_prop_by_name(node, "column") ) { + int ascending = e_xml_get_integer_prop_by_name(node, "ascending"); + ascending = ! ascending; + e_xml_set_integer_prop_by_name(node, "ascending", ascending); + break; + } + } + if ( !node ) { + } + if ( node && !strcmp(node->name, "leaf") ) { + if ( model_col == e_xml_get_integer_prop_by_name(node, "column") ) { + int ascending = e_xml_get_integer_prop_by_name(node, "ascending"); + ascending = ! ascending; + e_xml_set_integer_prop_by_name(node, "ascending", ascending); + } else { + e_xml_set_integer_prop_by_name(node, "ascending", 1); + e_xml_set_integer_prop_by_name(node, "column", model_col); + } + } + e_table_sort_info_changed(ethi->sort_info); + ethi_request_redraw (ethi); } if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); @@ -869,6 +962,8 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_SORT_INFO); /* * Create our pixmaps for DnD @@ -897,6 +992,8 @@ ethi_init (GnomeCanvasItem *item) ethi->drag_col = -1; ethi->drag_mark = -1; + + ethi->sort_info = NULL; } GtkType diff --git a/widgets/e-table/e-table-header-item.h b/widgets/e-table/e-table-header-item.h index 2e889a6adf..cc3cf8e4f6 100644 --- a/widgets/e-table/e-table-header-item.h +++ b/widgets/e-table/e-table-header-item.h @@ -1,8 +1,11 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_HEADER_ITEM_H_ #define _E_TABLE_HEADER_ITEM_H_ #include <libgnomeui/gnome-canvas.h> +#include <gnome-xml/tree.h> #include "e-table-header.h" +#include "e-table-sort-info.h" #define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ()) #define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem)) @@ -45,6 +48,11 @@ typedef struct { guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id; GnomeCanvasItem *drag_mark_item, *remove_item; GdkBitmap *stipple; + + /* + * For column sorting info + */ + ETableSortInfo *sort_info; } ETableHeaderItem; typedef struct { diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c index 527e7e22bc..8465f28567 100644 --- a/widgets/e-table/e-table-header.c +++ b/widgets/e-table/e-table-header.c @@ -350,3 +350,134 @@ e_table_header_set_frozen_columns (ETableHeader *eth, int idx) { eth->frozen_count = idx; } + +/* Forget model-view here. Really, this information belongs in the view anyway. */ +#if 0 +static void +set_arrows(ETableHeader *eth, ETableHeaderSortInfo info) +{ + ETableCol *col; + for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) { + if ( col->col_idx == info.model_col ) + e_table_column_set_arrow(col, info.ascending ? E_TABLE_COL_ARROW_DOWN : E_TABLE_COL_ARROW_UP); + } +} + +static void +unset_arrows(ETableHeader *eth, ETableHeaderSortInfo info) +{ + ETableCol *col; + for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) { + if ( col->col_idx == info.model_col ) + e_table_column_set_arrow(col, E_TABLE_COL_ARROW_NONE); + } +} + +ETableHeaderSortInfo +e_table_header_get_sort_info (ETableHeader *eth) +{ + ETableHeaderSortInfo dummy_info = {0, 1}; + g_return_val_if_fail (eth != NULL, dummy_info); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info); + + return eth->sort_info; +} + +void +e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + unset_arrows(eth, eth->sort_info); + eth->sort_info = info; + set_arrows(eth, eth->sort_info); + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + + +int +e_table_header_get_group_count (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0); + + return eth->grouping_count; +} + +ETableHeaderSortInfo * +e_table_header_get_groups (ETableHeader *eth) +{ + ETableHeaderSortInfo *ret; + g_return_val_if_fail (eth != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL); + + ret = g_new (ETableHeaderSortInfo, eth->grouping_count); + memcpy (ret, eth->grouping, sizeof (ETableHeaderSortInfo) * eth->grouping_count); + return eth->grouping; +} + +ETableHeaderSortInfo +e_table_header_get_group (ETableHeader *eth, gint index) +{ + ETableHeaderSortInfo dummy_info = {0, 1}; + g_return_val_if_fail (eth != NULL, dummy_info); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info); + g_return_val_if_fail (index >= 0, dummy_info); + g_return_val_if_fail (index < eth->grouping_count, dummy_info); + + return eth->grouping[index]; +} + +void +e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count + 1)); + memmove(eth->grouping + index + 1, eth->grouping + index, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index)); + eth->grouping[index] = info; + + eth->grouping_count ++; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_grouping_delete (ETableHeader *eth, gint index) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + memmove(eth->grouping + index, eth->grouping + index + 1, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index)); + eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - 1)); + + eth->grouping_count --; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx) +{ + ETableHeaderSortInfo info; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + if ( old_idx == new_idx ) + return; + + info = eth->grouping[old_idx]; + if ( old_idx < new_idx ) { + memmove(eth->grouping + old_idx, eth->grouping + old_idx + 1, sizeof(ETableHeaderSortInfo) * (new_idx - old_idx)); + } else { + memmove(eth->grouping + new_idx + 1, eth->grouping + new_idx, sizeof(ETableHeaderSortInfo) * (old_idx - new_idx)); + } + eth->grouping[new_idx] = info; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} +#endif diff --git a/widgets/e-table/e-table-header.h b/widgets/e-table/e-table-header.h index 0b4e40101f..cfd4d68d4a 100644 --- a/widgets/e-table/e-table-header.h +++ b/widgets/e-table/e-table-header.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_COLUMN_H_ #define _E_TABLE_COLUMN_H_ @@ -13,6 +14,13 @@ typedef struct _ETableHeader ETableHeader; #define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE)) #define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE)) +#if 0 +typedef struct { + int model_col; + int ascending; +} ETableHeaderSortInfo; +#endif + /* * A Columnar header. */ @@ -23,6 +31,12 @@ struct _ETableHeader { ETableCol **columns; gboolean selectable; int frozen_count; + +#if 0 + ETableHeaderSortInfo sort_info; + ETableHeaderSortInfo *grouping; + gint grouping_count; +#endif }; typedef struct { @@ -45,6 +59,19 @@ int e_table_header_index (ETableHeader *eth, int e_table_header_get_index_at (ETableHeader *eth, int x_offset); ETableCol **e_table_header_get_columns (ETableHeader *eth); + +#if 0 +ETableHeaderSortInfo e_table_header_get_sort_info (ETableHeader *eth); +void e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info); + +int e_table_header_get_group_count (ETableHeader *eth); +ETableHeaderSortInfo *e_table_header_get_groups (ETableHeader *eth); +ETableHeaderSortInfo e_table_header_get_group (ETableHeader *eth, gint index); +void e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info); +void e_table_header_grouping_delete (ETableHeader *eth, gint index); +void e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx); +#endif + gboolean e_table_header_selection_ok (ETableHeader *eth); int e_table_header_get_selected (ETableHeader *eth); int e_table_header_total_width (ETableHeader *eth); diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index ef14b98018..660ec20f91 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -156,7 +156,7 @@ e_table_model_get_type (void) { GtkTypeInfo info = { - "ETableModle", + "ETableModel", sizeof (ETableModel), sizeof (ETableModelClass), (GtkClassInitFunc) e_table_model_class_init, diff --git a/widgets/e-table/e-table-sort-info.c b/widgets/e-table/e-table-sort-info.c new file mode 100644 index 0000000000..1f465be99b --- /dev/null +++ b/widgets/e-table/e-table-sort-info.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-sort-info.c: a Table Model + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 Helix Code, Inc. + */ +#include <config.h> +#include <gtk/gtksignal.h> +#include <gnome-xml/tree.h> +#include "e-table-sort-info.h" + +#define ETM_CLASS(e) ((ETableSortInfoClass *)((GtkObject *)e)->klass) + +#define PARENT_TYPE gtk_object_get_type(); + + +static GtkObjectClass *e_table_sort_info_parent_class; + +enum { + SORT_INFO_CHANGED, + LAST_SIGNAL +}; + +static guint e_table_sort_info_signals [LAST_SIGNAL] = { 0, }; + +enum { + ARG_0, + ARG_GROUPING +}; + +static void +etsi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + ETableSortInfo *etsi; + + etsi = E_TABLE_SORT_INFO (o); + + switch (arg_id){ + case ARG_GROUPING: + etsi->grouping = GTK_VALUE_POINTER (*arg); + break; + } +} + +static void +etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + ETableSortInfo *etsi; + + etsi = E_TABLE_SORT_INFO (o); + + switch (arg_id){ + case ARG_GROUPING: + GTK_VALUE_POINTER (*arg) = etsi->grouping; + break; + } +} + +static void +e_table_sort_info_class_init (GtkObjectClass *object_class) +{ + e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class->set_arg = etsi_set_arg; + object_class->get_arg = etsi_get_arg; + + e_table_sort_info_signals [SORT_INFO_CHANGED] = + gtk_signal_new ("sort_info_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableSortInfoClass, sort_info_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); + + gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER, + GTK_ARG_READWRITE, ARG_GROUPING); +} + + +guint +e_table_sort_info_get_type (void) +{ + static guint type = 0; + + if (!type) + { + GtkTypeInfo info = + { + "ETableSortInfo", + sizeof (ETableSortInfo), + sizeof (ETableSortInfoClass), + (GtkClassInitFunc) e_table_sort_info_class_init, + NULL, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_object_get_type(), &info); + } + + return type; +} + +void +e_table_sort_info_changed (ETableSortInfo *e_table_sort_info) +{ + g_return_if_fail (e_table_sort_info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info)); + + gtk_signal_emit (GTK_OBJECT (e_table_sort_info), + e_table_sort_info_signals [SORT_INFO_CHANGED]); +} + +ETableSortInfo * +e_table_sort_info_new (void) +{ + return gtk_type_new (e_table_sort_info_get_type ()); +} diff --git a/widgets/e-table/e-table-sort-info.h b/widgets/e-table/e-table-sort-info.h new file mode 100644 index 0000000000..0fc4cd52ef --- /dev/null +++ b/widgets/e-table/e-table-sort-info.h @@ -0,0 +1,37 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_SORT_INFO_H_ +#define _E_TABLE_SORT_INFO_H_ + +#include <gtk/gtkobject.h> + +#define E_TABLE_SORT_INFO_TYPE (e_table_sort_info_get_type ()) +#define E_TABLE_SORT_INFO(o) (GTK_CHECK_CAST ((o), E_TABLE_SORT_INFO_TYPE, ETableSortInfo)) +#define E_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORT_INFO_TYPE, ETableSortInfoClass)) +#define E_IS_TABLE_SORT_INFO(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORT_INFO_TYPE)) +#define E_IS_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORT_INFO_TYPE)) + +typedef struct { + GtkObject base; + + xmlNode *grouping; +} ETableSortInfo; + +typedef struct { + GtkObjectClass parent_class; + + /* + * Signals + */ + void (*sort_info_changed) (ETableSortInfo *etm); +} ETableSortInfoClass; + +GtkType e_table_sort_info_get_type (void); + +/* + * Routines for emitting signals on the e_table + */ +void e_table_sort_info_changed (ETableSortInfo *e_table_sort_info); +ETableSortInfo *e_table_sort_info_new (void); + +#endif /* _E_TABLE_SORT_INFO_H_ */ diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 4bd4417cd0..b1c14b958a 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -35,6 +35,7 @@ static GtkObjectClass *e_table_parent_class; static void e_table_fill_table (ETable *e_table, ETableModel *model); +static gboolean changed_idle (gpointer data); static void et_destroy (GtkObject *object) @@ -44,6 +45,7 @@ et_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (et->model)); gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); + gtk_object_unref (GTK_OBJECT (et->sort_info)); gtk_widget_destroy (GTK_WIDGET (et->header_canvas)); gtk_widget_destroy (GTK_WIDGET (et->table_canvas)); @@ -53,6 +55,9 @@ et_destroy (GtkObject *object) et->table_row_change_id); gtk_signal_disconnect (GTK_OBJECT (et->model), et->table_cell_change_id); + if (et->sort_info_change_id) + gtk_signal_disconnect (GTK_OBJECT (et->model), + et->sort_info_change_id); if (et->rebuild_idle_id) { g_source_remove(et->rebuild_idle_id); @@ -68,6 +73,9 @@ static void e_table_init (GtkObject *object) { ETable *e_table = E_TABLE (object); + + e_table->sort_info = NULL; + e_table->sort_info_change_id = 0; e_table->draw_grid = 1; e_table->draw_focus = 1; @@ -110,18 +118,46 @@ header_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t } static void +sort_info_changed (ETableSortInfo *info, ETable *et) +{ + et->need_rebuild = TRUE; + if ( !et->rebuild_idle_id ) { + et->rebuild_idle_id = g_idle_add(changed_idle, et); + } +} + +static void e_table_setup_header (ETable *e_table) { + xmlNode *root; + xmlNode *grouping; e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ()); - + gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); + root = xmlDocGetRootElement(e_table->specification); + grouping = e_xml_get_child_by_name(root, "grouping"); + + e_table->sort_info = e_table_sort_info_new(); + + gtk_object_ref(GTK_OBJECT(e_table->sort_info)); + gtk_object_sink(GTK_OBJECT(e_table->sort_info)); + + gtk_object_set(GTK_OBJECT(e_table->sort_info), + "grouping", grouping, + NULL); + + e_table->sort_info_change_id = + gtk_signal_connect (GTK_OBJECT(e_table->sort_info), "sort_info_changed", + GTK_SIGNAL_FUNC (sort_info_changed), e_table); + e_table->header_item = gnome_canvas_item_new ( gnome_canvas_root (e_table->header_canvas), e_table_header_item_get_type (), "ETableHeader", e_table->header, "x", 0, "y", 0, + "sort_info", e_table->sort_info, NULL); gtk_signal_connect ( @@ -705,7 +741,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, gtk_widget_show (vscrollbar); gtk_table_attach ( GTK_TABLE (e_table), vscrollbar, - 1, 2, 1, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0); + 1, 2, 0, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0); gtk_widget_pop_colormap (); gtk_widget_pop_visual (); diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index 5c29c1fa0c..9c5bb9b8a0 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -8,6 +8,7 @@ #include "e-table-model.h" #include "e-table-header.h" #include "e-table-group.h" +#include "e-table-sort-info.h" BEGIN_GNOME_DECLS @@ -26,10 +27,14 @@ typedef struct { ETableGroup *group; + ETableSortInfo *sort_info; + int table_model_change_id; int table_row_change_id; int table_cell_change_id; + int sort_info_change_id; + GnomeCanvas *header_canvas, *table_canvas; GnomeCanvasItem *header_item, *root; diff --git a/widgets/table/e-table-col.h b/widgets/table/e-table-col.h index c6f9c9dfb5..816879792e 100644 --- a/widgets/table/e-table-col.h +++ b/widgets/table/e-table-col.h @@ -16,7 +16,7 @@ typedef struct _ETableColClass ETableColClass; typedef enum _ETableColArrow ETableColArrow; enum _ETableColArrow { - E_TABLE_COL_ARROW_NONE, + E_TABLE_COL_ARROW_NONE = 0, E_TABLE_COL_ARROW_UP, E_TABLE_COL_ARROW_DOWN }; diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c index 475e15c31d..82637a8a82 100644 --- a/widgets/table/e-table-header-item.c +++ b/widgets/table/e-table-header-item.c @@ -16,6 +16,7 @@ #include <libgnomeui/gnome-canvas-rect-ellipse.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include "e-util/e-cursors.h" +#include "e-util/e-xml-utils.h" #include "e-table-header.h" #include "e-table-header-item.h" #include "e-table-col-dnd.h" @@ -55,7 +56,8 @@ enum { ARG_TABLE_HEADER, ARG_TABLE_X, ARG_TABLE_Y, - ARG_TABLE_FONTSET + ARG_TABLE_FONTSET, + ARG_SORT_INFO }; static GtkTargetEntry ethi_drag_types [] = { @@ -71,6 +73,8 @@ ethi_destroy (GtkObject *object){ ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object); ethi_drop_table_header (ethi); + if ( ethi->sort_info ) + gtk_object_unref(GTK_OBJECT(ethi->sort_info)); if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object); @@ -181,6 +185,11 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) case ARG_TABLE_FONTSET: ethi_font_load (ethi, GTK_VALUE_STRING (*arg)); break; + + case ARG_SORT_INFO: + ethi->sort_info = GTK_VALUE_POINTER (*arg); + gtk_object_ref(GTK_OBJECT(ethi->sort_info)); + break; } ethi_update (item, NULL, NULL, 0); @@ -482,7 +491,7 @@ ethi_unrealize (GnomeCanvasItem *item) static void draw_button (ETableHeaderItem *ethi, ETableCol *col, GdkDrawable *drawable, GdkGC *gc, GtkStyle *style, - int x, int y, int width, int height) + int x, int y, int width, int height, ETableColArrow arrow) { GdkRectangle clip; int xtra; @@ -532,7 +541,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, col->text, strlen (col->text)); } - switch ( e_table_col_get_arrow(col) ) { + switch ( arrow ) { case E_TABLE_COL_ARROW_NONE: break; case E_TABLE_COL_ARROW_UP: @@ -544,7 +553,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, &clip, GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas), "header", - e_table_col_get_arrow(col) == E_TABLE_COL_ARROW_UP ? GTK_ARROW_UP : GTK_ARROW_DOWN, + (arrow == E_TABLE_COL_ARROW_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, TRUE, x + PADDING / 2 + clip.width - MIN_ARROW_SIZE - 2, y + (ethi->height - MIN_ARROW_SIZE) / 2, @@ -563,11 +572,34 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width const int cols = e_table_header_count (ethi->eth); int x1, x2; int col; + GHashTable *arrows = g_hash_table_new(NULL, NULL); + xmlNode *node; #if 0 printf ("My coords are: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); #endif + + if (ethi->sort_info) { + xmlNode *grouping; + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + for (node = grouping->childs; node && strcmp(node->name, "leaf"); node = node->childs) { + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + if ( node ) + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + x1 = x2 = ethi->x1; for (col = 0; col < cols; col++, x1 = x2){ ETableCol *ecol = e_table_header_get_column (ethi->eth, col); @@ -590,8 +622,10 @@ ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width draw_button (ethi, ecol, drawable, gc, GTK_WIDGET (canvas)->style, - x1 - x, ethi->y1 - y, col_width, ethi->height); + x1 - x, ethi->y1 - y, col_width, ethi->height, + (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) ); } + g_hash_table_destroy(arrows); } static double @@ -698,6 +732,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) int col_width; GdkPixmap *pixmap; GdkGC *gc; + GHashTable *arrows = g_hash_table_new(NULL, NULL); + xmlNode *node; ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x); if ( ethi->drag_col < ethi->eth->frozen_count && ethi->drag_col >= 0 ) { @@ -707,6 +743,27 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) if (ethi->drag_col == -1) return; + + if (ethi->sort_info) { + xmlNode *grouping; + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + for (node = grouping->childs; node && strcmp(node->name, "leaf"); node = node->childs) { + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + if ( node ) + g_hash_table_insert(arrows, + (gpointer) e_xml_get_integer_prop_by_name(node, "column"), + (gpointer) (e_xml_get_integer_prop_by_name(node, "ascending") ? + E_TABLE_COL_ARROW_DOWN : + E_TABLE_COL_ARROW_UP)); + } + list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types)); context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event); @@ -719,7 +776,8 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) gc = widget->style->bg_gc [GTK_STATE_ACTIVE]; draw_button (ethi, ecol, pixmap, gc, widget->style, - 0, 0, col_width, ethi->height); + 0, 0, col_width, ethi->height, + (ETableColArrow) g_hash_table_lookup(arrows, (gpointer) ecol->col_idx) ); gtk_drag_set_icon_pixmap (context, gdk_window_get_colormap(widget->window), pixmap, @@ -729,6 +787,7 @@ ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event) gdk_pixmap_unref(pixmap); ethi->maybe_drag = FALSE; + g_hash_table_destroy(arrows); } /* @@ -830,6 +889,40 @@ ethi_event (GnomeCanvasItem *item, GdkEvent *e) if (ethi->resize_col != -1){ needs_ungrab = (ethi->resize_guide != NULL); ethi_end_resize (ethi, ethi->resize_width); + } else if (ethi->maybe_drag && ethi->sort_info) { + ETableCol *col; + int model_col; + xmlNode *node; + xmlNode *grouping; + + gtk_object_get(GTK_OBJECT(ethi->sort_info), + "grouping", &grouping, + NULL); + + col = e_table_header_get_column(ethi->eth, ethi_find_col_by_x (ethi, e->button.x)); + model_col = col->col_idx; + for (node = grouping->childs; node->childs && strcmp(node->name, "leaf"); node = node->childs) { + if ( model_col == e_xml_get_integer_prop_by_name(node, "column") ) { + int ascending = e_xml_get_integer_prop_by_name(node, "ascending"); + ascending = ! ascending; + e_xml_set_integer_prop_by_name(node, "ascending", ascending); + break; + } + } + if ( !node ) { + } + if ( node && !strcmp(node->name, "leaf") ) { + if ( model_col == e_xml_get_integer_prop_by_name(node, "column") ) { + int ascending = e_xml_get_integer_prop_by_name(node, "ascending"); + ascending = ! ascending; + e_xml_set_integer_prop_by_name(node, "ascending", ascending); + } else { + e_xml_set_integer_prop_by_name(node, "ascending", 1); + e_xml_set_integer_prop_by_name(node, "column", model_col); + } + } + e_table_sort_info_changed(ethi->sort_info); + ethi_request_redraw (ethi); } if (needs_ungrab) gnome_canvas_item_ungrab (item, e->button.time); @@ -869,6 +962,8 @@ ethi_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_TABLE_FONTSET); + gtk_object_add_arg_type ("ETableHeaderItem::sort_info", GTK_TYPE_POINTER, + GTK_ARG_WRITABLE, ARG_SORT_INFO); /* * Create our pixmaps for DnD @@ -897,6 +992,8 @@ ethi_init (GnomeCanvasItem *item) ethi->drag_col = -1; ethi->drag_mark = -1; + + ethi->sort_info = NULL; } GtkType diff --git a/widgets/table/e-table-header-item.h b/widgets/table/e-table-header-item.h index 2e889a6adf..cc3cf8e4f6 100644 --- a/widgets/table/e-table-header-item.h +++ b/widgets/table/e-table-header-item.h @@ -1,8 +1,11 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_HEADER_ITEM_H_ #define _E_TABLE_HEADER_ITEM_H_ #include <libgnomeui/gnome-canvas.h> +#include <gnome-xml/tree.h> #include "e-table-header.h" +#include "e-table-sort-info.h" #define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ()) #define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem)) @@ -45,6 +48,11 @@ typedef struct { guint drag_motion_id, drag_end_id, drag_leave_id, drag_drop_id; GnomeCanvasItem *drag_mark_item, *remove_item; GdkBitmap *stipple; + + /* + * For column sorting info + */ + ETableSortInfo *sort_info; } ETableHeaderItem; typedef struct { diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c index 527e7e22bc..8465f28567 100644 --- a/widgets/table/e-table-header.c +++ b/widgets/table/e-table-header.c @@ -350,3 +350,134 @@ e_table_header_set_frozen_columns (ETableHeader *eth, int idx) { eth->frozen_count = idx; } + +/* Forget model-view here. Really, this information belongs in the view anyway. */ +#if 0 +static void +set_arrows(ETableHeader *eth, ETableHeaderSortInfo info) +{ + ETableCol *col; + for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) { + if ( col->col_idx == info.model_col ) + e_table_column_set_arrow(col, info.ascending ? E_TABLE_COL_ARROW_DOWN : E_TABLE_COL_ARROW_UP); + } +} + +static void +unset_arrows(ETableHeader *eth, ETableHeaderSortInfo info) +{ + ETableCol *col; + for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) { + if ( col->col_idx == info.model_col ) + e_table_column_set_arrow(col, E_TABLE_COL_ARROW_NONE); + } +} + +ETableHeaderSortInfo +e_table_header_get_sort_info (ETableHeader *eth) +{ + ETableHeaderSortInfo dummy_info = {0, 1}; + g_return_val_if_fail (eth != NULL, dummy_info); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info); + + return eth->sort_info; +} + +void +e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + unset_arrows(eth, eth->sort_info); + eth->sort_info = info; + set_arrows(eth, eth->sort_info); + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + + +int +e_table_header_get_group_count (ETableHeader *eth) +{ + g_return_val_if_fail (eth != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0); + + return eth->grouping_count; +} + +ETableHeaderSortInfo * +e_table_header_get_groups (ETableHeader *eth) +{ + ETableHeaderSortInfo *ret; + g_return_val_if_fail (eth != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL); + + ret = g_new (ETableHeaderSortInfo, eth->grouping_count); + memcpy (ret, eth->grouping, sizeof (ETableHeaderSortInfo) * eth->grouping_count); + return eth->grouping; +} + +ETableHeaderSortInfo +e_table_header_get_group (ETableHeader *eth, gint index) +{ + ETableHeaderSortInfo dummy_info = {0, 1}; + g_return_val_if_fail (eth != NULL, dummy_info); + g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info); + g_return_val_if_fail (index >= 0, dummy_info); + g_return_val_if_fail (index < eth->grouping_count, dummy_info); + + return eth->grouping[index]; +} + +void +e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count + 1)); + memmove(eth->grouping + index + 1, eth->grouping + index, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index)); + eth->grouping[index] = info; + + eth->grouping_count ++; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_grouping_delete (ETableHeader *eth, gint index) +{ + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + memmove(eth->grouping + index, eth->grouping + index + 1, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index)); + eth->grouping = g_realloc(eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - 1)); + + eth->grouping_count --; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} + +void +e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx) +{ + ETableHeaderSortInfo info; + + g_return_if_fail (eth != NULL); + g_return_if_fail (E_IS_TABLE_HEADER (eth)); + + if ( old_idx == new_idx ) + return; + + info = eth->grouping[old_idx]; + if ( old_idx < new_idx ) { + memmove(eth->grouping + old_idx, eth->grouping + old_idx + 1, sizeof(ETableHeaderSortInfo) * (new_idx - old_idx)); + } else { + memmove(eth->grouping + new_idx + 1, eth->grouping + new_idx, sizeof(ETableHeaderSortInfo) * (old_idx - new_idx)); + } + eth->grouping[new_idx] = info; + + gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]); +} +#endif diff --git a/widgets/table/e-table-header.h b/widgets/table/e-table-header.h index 0b4e40101f..cfd4d68d4a 100644 --- a/widgets/table/e-table-header.h +++ b/widgets/table/e-table-header.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_COLUMN_H_ #define _E_TABLE_COLUMN_H_ @@ -13,6 +14,13 @@ typedef struct _ETableHeader ETableHeader; #define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE)) #define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE)) +#if 0 +typedef struct { + int model_col; + int ascending; +} ETableHeaderSortInfo; +#endif + /* * A Columnar header. */ @@ -23,6 +31,12 @@ struct _ETableHeader { ETableCol **columns; gboolean selectable; int frozen_count; + +#if 0 + ETableHeaderSortInfo sort_info; + ETableHeaderSortInfo *grouping; + gint grouping_count; +#endif }; typedef struct { @@ -45,6 +59,19 @@ int e_table_header_index (ETableHeader *eth, int e_table_header_get_index_at (ETableHeader *eth, int x_offset); ETableCol **e_table_header_get_columns (ETableHeader *eth); + +#if 0 +ETableHeaderSortInfo e_table_header_get_sort_info (ETableHeader *eth); +void e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info); + +int e_table_header_get_group_count (ETableHeader *eth); +ETableHeaderSortInfo *e_table_header_get_groups (ETableHeader *eth); +ETableHeaderSortInfo e_table_header_get_group (ETableHeader *eth, gint index); +void e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info); +void e_table_header_grouping_delete (ETableHeader *eth, gint index); +void e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx); +#endif + gboolean e_table_header_selection_ok (ETableHeader *eth); int e_table_header_get_selected (ETableHeader *eth); int e_table_header_total_width (ETableHeader *eth); diff --git a/widgets/table/e-table-model.c b/widgets/table/e-table-model.c index ef14b98018..660ec20f91 100644 --- a/widgets/table/e-table-model.c +++ b/widgets/table/e-table-model.c @@ -156,7 +156,7 @@ e_table_model_get_type (void) { GtkTypeInfo info = { - "ETableModle", + "ETableModel", sizeof (ETableModel), sizeof (ETableModelClass), (GtkClassInitFunc) e_table_model_class_init, diff --git a/widgets/table/e-table-sort-info.c b/widgets/table/e-table-sort-info.c new file mode 100644 index 0000000000..1f465be99b --- /dev/null +++ b/widgets/table/e-table-sort-info.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * e-table-sort-info.c: a Table Model + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 Helix Code, Inc. + */ +#include <config.h> +#include <gtk/gtksignal.h> +#include <gnome-xml/tree.h> +#include "e-table-sort-info.h" + +#define ETM_CLASS(e) ((ETableSortInfoClass *)((GtkObject *)e)->klass) + +#define PARENT_TYPE gtk_object_get_type(); + + +static GtkObjectClass *e_table_sort_info_parent_class; + +enum { + SORT_INFO_CHANGED, + LAST_SIGNAL +}; + +static guint e_table_sort_info_signals [LAST_SIGNAL] = { 0, }; + +enum { + ARG_0, + ARG_GROUPING +}; + +static void +etsi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + ETableSortInfo *etsi; + + etsi = E_TABLE_SORT_INFO (o); + + switch (arg_id){ + case ARG_GROUPING: + etsi->grouping = GTK_VALUE_POINTER (*arg); + break; + } +} + +static void +etsi_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + ETableSortInfo *etsi; + + etsi = E_TABLE_SORT_INFO (o); + + switch (arg_id){ + case ARG_GROUPING: + GTK_VALUE_POINTER (*arg) = etsi->grouping; + break; + } +} + +static void +e_table_sort_info_class_init (GtkObjectClass *object_class) +{ + e_table_sort_info_parent_class = gtk_type_class (gtk_object_get_type ()); + + object_class->set_arg = etsi_set_arg; + object_class->get_arg = etsi_get_arg; + + e_table_sort_info_signals [SORT_INFO_CHANGED] = + gtk_signal_new ("sort_info_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableSortInfoClass, sort_info_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, e_table_sort_info_signals, LAST_SIGNAL); + + gtk_object_add_arg_type ("ETableSortInfo::grouping", GTK_TYPE_POINTER, + GTK_ARG_READWRITE, ARG_GROUPING); +} + + +guint +e_table_sort_info_get_type (void) +{ + static guint type = 0; + + if (!type) + { + GtkTypeInfo info = + { + "ETableSortInfo", + sizeof (ETableSortInfo), + sizeof (ETableSortInfoClass), + (GtkClassInitFunc) e_table_sort_info_class_init, + NULL, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_object_get_type(), &info); + } + + return type; +} + +void +e_table_sort_info_changed (ETableSortInfo *e_table_sort_info) +{ + g_return_if_fail (e_table_sort_info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (e_table_sort_info)); + + gtk_signal_emit (GTK_OBJECT (e_table_sort_info), + e_table_sort_info_signals [SORT_INFO_CHANGED]); +} + +ETableSortInfo * +e_table_sort_info_new (void) +{ + return gtk_type_new (e_table_sort_info_get_type ()); +} diff --git a/widgets/table/e-table-sort-info.h b/widgets/table/e-table-sort-info.h new file mode 100644 index 0000000000..0fc4cd52ef --- /dev/null +++ b/widgets/table/e-table-sort-info.h @@ -0,0 +1,37 @@ + +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_SORT_INFO_H_ +#define _E_TABLE_SORT_INFO_H_ + +#include <gtk/gtkobject.h> + +#define E_TABLE_SORT_INFO_TYPE (e_table_sort_info_get_type ()) +#define E_TABLE_SORT_INFO(o) (GTK_CHECK_CAST ((o), E_TABLE_SORT_INFO_TYPE, ETableSortInfo)) +#define E_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORT_INFO_TYPE, ETableSortInfoClass)) +#define E_IS_TABLE_SORT_INFO(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORT_INFO_TYPE)) +#define E_IS_TABLE_SORT_INFO_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORT_INFO_TYPE)) + +typedef struct { + GtkObject base; + + xmlNode *grouping; +} ETableSortInfo; + +typedef struct { + GtkObjectClass parent_class; + + /* + * Signals + */ + void (*sort_info_changed) (ETableSortInfo *etm); +} ETableSortInfoClass; + +GtkType e_table_sort_info_get_type (void); + +/* + * Routines for emitting signals on the e_table + */ +void e_table_sort_info_changed (ETableSortInfo *e_table_sort_info); +ETableSortInfo *e_table_sort_info_new (void); + +#endif /* _E_TABLE_SORT_INFO_H_ */ diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 4bd4417cd0..b1c14b958a 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -35,6 +35,7 @@ static GtkObjectClass *e_table_parent_class; static void e_table_fill_table (ETable *e_table, ETableModel *model); +static gboolean changed_idle (gpointer data); static void et_destroy (GtkObject *object) @@ -44,6 +45,7 @@ et_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (et->model)); gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); + gtk_object_unref (GTK_OBJECT (et->sort_info)); gtk_widget_destroy (GTK_WIDGET (et->header_canvas)); gtk_widget_destroy (GTK_WIDGET (et->table_canvas)); @@ -53,6 +55,9 @@ et_destroy (GtkObject *object) et->table_row_change_id); gtk_signal_disconnect (GTK_OBJECT (et->model), et->table_cell_change_id); + if (et->sort_info_change_id) + gtk_signal_disconnect (GTK_OBJECT (et->model), + et->sort_info_change_id); if (et->rebuild_idle_id) { g_source_remove(et->rebuild_idle_id); @@ -68,6 +73,9 @@ static void e_table_init (GtkObject *object) { ETable *e_table = E_TABLE (object); + + e_table->sort_info = NULL; + e_table->sort_info_change_id = 0; e_table->draw_grid = 1; e_table->draw_focus = 1; @@ -110,18 +118,46 @@ header_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_t } static void +sort_info_changed (ETableSortInfo *info, ETable *et) +{ + et->need_rebuild = TRUE; + if ( !et->rebuild_idle_id ) { + et->rebuild_idle_id = g_idle_add(changed_idle, et); + } +} + +static void e_table_setup_header (ETable *e_table) { + xmlNode *root; + xmlNode *grouping; e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ()); - + gtk_widget_show (GTK_WIDGET (e_table->header_canvas)); + root = xmlDocGetRootElement(e_table->specification); + grouping = e_xml_get_child_by_name(root, "grouping"); + + e_table->sort_info = e_table_sort_info_new(); + + gtk_object_ref(GTK_OBJECT(e_table->sort_info)); + gtk_object_sink(GTK_OBJECT(e_table->sort_info)); + + gtk_object_set(GTK_OBJECT(e_table->sort_info), + "grouping", grouping, + NULL); + + e_table->sort_info_change_id = + gtk_signal_connect (GTK_OBJECT(e_table->sort_info), "sort_info_changed", + GTK_SIGNAL_FUNC (sort_info_changed), e_table); + e_table->header_item = gnome_canvas_item_new ( gnome_canvas_root (e_table->header_canvas), e_table_header_item_get_type (), "ETableHeader", e_table->header, "x", 0, "y", 0, + "sort_info", e_table->sort_info, NULL); gtk_signal_connect ( @@ -705,7 +741,7 @@ et_real_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, gtk_widget_show (vscrollbar); gtk_table_attach ( GTK_TABLE (e_table), vscrollbar, - 1, 2, 1, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0); + 1, 2, 0, 2, 0, GTK_FILL | GTK_EXPAND, 0, 0); gtk_widget_pop_colormap (); gtk_widget_pop_visual (); diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index 5c29c1fa0c..9c5bb9b8a0 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -8,6 +8,7 @@ #include "e-table-model.h" #include "e-table-header.h" #include "e-table-group.h" +#include "e-table-sort-info.h" BEGIN_GNOME_DECLS @@ -26,10 +27,14 @@ typedef struct { ETableGroup *group; + ETableSortInfo *sort_info; + int table_model_change_id; int table_row_change_id; int table_cell_change_id; + int sort_info_change_id; + GnomeCanvas *header_canvas, *table_canvas; GnomeCanvasItem *header_item, *root; |