diff options
Diffstat (limited to 'widgets/e-table')
30 files changed, 2082 insertions, 388 deletions
diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index 88ad00e78a..5ed89f05ef 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,73 @@ +2000-02-24 Christopher James Lahey <clahey@helixcode.com> + + * e-table-subset-variable.c, e-table-subset-variable.h: A new + model which is a subset, but you can add and remove rows. + + * test-table.c: Added a thaw method for use with the + e-table-subset (emits model_changed.) Adapted to the changes to + e_table_item. Properly parse headers. Adapted to the changes to + e_table, including creating example xml spec data. + + * test-cols.c, test-check.c: Added a thaw method for use with the + e-table-subset (emits model_changed.) Adapted to the changes to + e_table_item. + + * e-table.c, e-table.h: Reworked e-table to use the ETable + grouping system. The only difference for the interface is that + instead of passing in a column_spec and a grouping_spec, you pass + in a single string that is an xml format that includes both pieces + of information. + + * e-table-subset.h: Added rules for emacs to do correct + indentation. + + * e-table-subset.c: Implemented freezing. No signals are emitted + while frozen and "model_changed" is emitted when thawed. + + * e-table-sorted.h: ETableSortedClass has ETableSubset as its + parent object instead of ETableSubsetClass. Fixed this. + + * e-table-simple.c, e-table-simple.h: Implemented the thaw method. + Use of simple now requires an extra argument (the thaw method.) + + * e-table-model.h, e-table-model.c: Added e_table_model_freeze and + e_table_model_thaw. + + * e-table-item.h, e-table-item.c: Reworked this a bit to make it + provide some things the new group system needed and to make + inter-item keyboard focus work. Changed the external interface + only in the list of arguments it recognizes and signals it emits. + Instead of "x" and "y", you have to use + e_canvas_item_move_absolute and instead of emitting a + "height_changed" signal, it emits a "resize" signal. There's new + "has_focus", "width", and "height" arguments and a function to get + the currently focused column. + + * e-table-header-item.c: Got rid of some warnings here. Changed + the + + * e-table-group-leaf.h, e-table-group-leaf.c, + e-table-group-container.h, e-table-group-container.c: New types to + make e_table_group work properly. + + * e-table-group.h, e-table-group.c: Completely reworked e-table + grouping. e-table-group now uses a hierarchical structure. + + * e-cell.h: Added e_cell_print. This doesn't work yet. + + * e-cell.c: Made e_cell_realize exist. (It was improperly named + e_cell_view_realize in the .c.) + + * e-cell-text.c: Made the blinking cursor disappear properly. + + * check-filled.xpm, check-empty.xpm: Made these const char *[] + instead of char *[] to avoid compiler warnings. + + * Makefile.am: Added e-table-group-container.c, + e-table-group-container.h, e-table-group-leaf.c, + e-table-group-leaf.h, e-table-subset-variable.c, + e-table-subset-variable.h. + 2000-02-18 Miguel de Icaza <miguel@nuclecu.unam.mx> * e-table-header.c: Include <string.h> diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am index 556a77bad8..0780ae7c57 100644 --- a/widgets/e-table/Makefile.am +++ b/widgets/e-table/Makefile.am @@ -23,6 +23,10 @@ libetable_a_SOURCES = \ e-table-col.h \ e-table-group.c \ e-table-group.h \ + e-table-group-container.c \ + e-table-group-container.h \ + e-table-group-leaf.c \ + e-table-group-leaf.h \ e-table-header.c \ e-table-header.h \ e-table-header-item.c \ @@ -36,7 +40,9 @@ libetable_a_SOURCES = \ e-table-sorted.c \ e-table-sorted.h \ e-table-subset.c \ - e-table-subset.h + e-table-subset.h \ + e-table-subset-variable.c \ + e-table-subset-variable.h noinst_PROGRAMS = \ table-test diff --git a/widgets/e-table/check-empty.xpm b/widgets/e-table/check-empty.xpm index 2dd873e137..746b20234e 100644 --- a/widgets/e-table/check-empty.xpm +++ b/widgets/e-table/check-empty.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_empty_xpm[] = { +static const char * check_empty_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/e-table/check-filled.xpm b/widgets/e-table/check-filled.xpm index 689d7a7967..c0468fc25b 100644 --- a/widgets/e-table/check-filled.xpm +++ b/widgets/e-table/check-filled.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char * check_filled_xpm[] = { +static const char * check_filled_xpm[] = { "16 16 2 1", " c None", ". c #000000", diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index 8131d16384..fb33f10537 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -120,7 +120,6 @@ typedef struct { } ECellTextView; typedef struct _CurrentCell{ - ECellTextView *text_view; int width; gchar *text; @@ -233,6 +232,10 @@ static void ect_stop_editing (ECellTextView *text_view) { CellEdit *edit = text_view->edit; + int row, view_col; + + row = edit->cell.row; + view_col = edit->cell.view_col; g_free (edit->old_text); edit->old_text = NULL; @@ -246,12 +249,24 @@ ect_stop_editing (ECellTextView *text_view) g_free(edit->primary_selection); if (edit->clipboard_selection) g_free(edit->clipboard_selection); + if ( ! edit->default_cursor_shown ) { + gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); + edit->default_cursor_shown = TRUE; + } + if (edit->timeout_id) { + g_source_remove(edit->timeout_id); + edit->timeout_id = 0; + } + if (edit->timer) { + g_timer_stop(edit->timer); + g_timer_destroy(edit->timer); + edit->timer = NULL; + } g_free (edit); text_view->edit = NULL; - - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); + ect_queue_redraw (text_view, view_col, row); } /* @@ -260,7 +275,6 @@ ect_stop_editing (ECellTextView *text_view) static void ect_cancel_edit (ECellTextView *text_view) { - ect_queue_redraw (text_view, text_view->edit->cell.view_col, text_view->edit->cell.row); ect_stop_editing (text_view); } @@ -379,9 +393,11 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, if (edit){ - if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) + if ((edit->cell.view_col == view_col) && (edit->cell.row == row)) { edit_display = TRUE; - fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + fg_gc = canvas->style->fg_gc[edit->has_selection ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]; + } else + fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } else { fg_gc = canvas->style->fg_gc[GTK_STATE_ACTIVE]; } @@ -776,6 +792,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, break; case GDK_BUTTON_PRESS: /* Fall Through */ case GDK_BUTTON_RELEASE: + event->button.x -= 4; + event->button.y -= 1; if ((!edit_display) && ect->editable && event->type == GDK_BUTTON_RELEASE @@ -828,6 +846,8 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, } break; case GDK_MOTION_NOTIFY: + event->motion.x -= 4; + event->motion.y -= 1; if (edit_display) { GdkEventMotion motion = event->motion; e_tep_event.motion.time = motion.time; @@ -928,15 +948,6 @@ ect_height (ECellView *ecell_view, int model_col, int view_col, int row) } /* - * Callback: invoked when the user pressed "enter" on the GtkEntry - */ -static void -ect_entry_activate (GtkEntry *entry, ECellTextView *text_view) -{ - e_table_item_leave_edit (text_view->cell_view.e_table_item_view); -} - -/* * ECellView::enter_edit method */ static void * @@ -1011,19 +1022,6 @@ ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, voi CellEdit *edit = text_view->edit; if (edit){ - if ( ! edit->default_cursor_shown ) { - gdk_window_set_cursor(GTK_WIDGET(text_view->canvas)->window, NULL); - edit->default_cursor_shown = TRUE; - } - if (edit->timeout_id) { - g_source_remove(edit->timeout_id); - edit->timeout_id = 0; - } - if (edit->timer) { - g_timer_stop(edit->timer); - g_timer_destroy(edit->timer); - edit->timer = NULL; - } ect_accept_edits (text_view); ect_stop_editing (text_view); } else { @@ -1508,9 +1506,6 @@ e_cell_text_view_command(ETextEventProcessor *tep, ETextEventProcessorCommand *c break; case E_TEP_ACTIVATE: e_table_item_leave_edit (text_view->cell_view.e_table_item_view); - if (edit->timer) { - g_timer_reset(edit->timer); - } break; case E_TEP_SET_SELECT_BY_WORD: edit->select_by_word = command->value; @@ -1842,7 +1837,9 @@ calc_line_widths (CurrentCell *cell) } if (ect->use_ellipsis && - ! text_view->edit && + (!(text_view->edit && + cell->row == text_view->edit->cell.row && + cell->view_col == text_view->edit->cell.view_col)) && lines->width > cell->width) { if (font) { lines->ellipsis_length = 0; diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c index f1345e8c6b..1d87019007 100644 --- a/widgets/e-table/e-cell.c +++ b/widgets/e-table/e-cell.c @@ -129,7 +129,7 @@ e_cell_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view } void -e_cell_view_realize (ECellView *ecell_view) +e_cell_realize (ECellView *ecell_view) { return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->realize (ecell_view); } diff --git a/widgets/e-table/e-cell.h b/widgets/e-table/e-cell.h index 3c258689e4..b21653d6d1 100644 --- a/widgets/e-table/e-cell.h +++ b/widgets/e-table/e-cell.h @@ -2,6 +2,7 @@ #define _E_CELL_H_ #include <gdk/gdktypes.h> +#include <libgnomeprint/gnome-print.h> #include "e-table-model.h" #define E_CELL_TYPE (e_cell_get_type ()) @@ -62,6 +63,9 @@ void e_cell_unrealize (ECellView *ecell_view); void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr, int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2); +void e_cell_print (ECellView *ecell_view, GnomePrintContext *context, + int model_col, int view_col, int row, + double width, double height); void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2); void e_cell_unfocus (ECellView *ecell_view); diff --git a/widgets/e-table/e-table-group-container.c b/widgets/e-table/e-table-group-container.c new file mode 100644 index 0000000000..a9f494db04 --- /dev/null +++ b/widgets/e-table/e-table-group-container.c @@ -0,0 +1,804 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-container.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" +#include "e-util/e-canvas-utils.h" +#include "widgets/e-text/e-text.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define BUTTON_HEIGHT 10 +#define BUTTON_PADDING 2 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgc_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static int etgc_event (GnomeCanvasItem *item, GdkEvent *event); +static void etgc_realize (GnomeCanvasItem *item); +static void etgc_unrealize (GnomeCanvasItem *item); + +static void etgc_add (ETableGroup *etg, gint row); +static gboolean etgc_remove (ETableGroup *etg, gint row); +static void etgc_increment (ETableGroup *etg, gint position, gint amount); +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col); + +static void etgc_child_resize (GtkObject *object, gpointer data); + +static void etgc_queue_reposition (ETableGroupContainer *etgc); + +typedef struct { + ETableGroup *child; + void *key; + GnomeCanvasItem *text; + GnomeCanvasItem *rect; + gint count; +} ETableGroupContainerChildNode; + +static void +etgc_destroy (GtkObject *object) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (object); + + gdk_font_unref(etgc->font); + + GTK_OBJECT_CLASS (etgc_parent_class)->destroy (object); +} +#if 0 +void +e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etg != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etg->children = g_list_append (etg->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etg->transparent ? 0 : TITLE_HEIGHT; + int x = etg->transparent ? 0 : GROUP_INDENT; + + for (l = etg->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etg_relayout), etg); + } + } +} + +static void +etg_realize (GnomeCanvasItem *item) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroup *etg = E_TABLE_GROUP (item); + + GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); + + if (!etg->transparent){ + int current_width, current_height; + + etg_dim (etg, ¤t_width, ¤t_height); + + if ((current_height != etg->height) || (current_width != etg->width)){ + etg->width = current_width; + etg->height = current_height; + + gnome_canvas_item_set ( + etg->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etg->width, + "y2", (double) etg->height, + NULL); + } + } +} +#endif + +void +e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgc), full_header, header, model); + etgc->ecol = ecol; + etgc->child_rules = child_rules; + + etgc->font = gdk_font_load ("lucidasans-10"); +#if 0 + etgc->open = open; + etgc->transparent = transparent; + + etgc_dim (etgc, &etgc->width, &etgc->height); + + if (!etgc->transparent) + etgc->rect = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (etgc), + gnome_canvas_rect_get_type (), + "fill_color", "gray", + "outline_color", "gray20", + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); +#endif + +#if 0 + /* + * Reparent the child into our space. + */ + gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etgc)); + + gnome_canvas_item_set ( + child, + "x", (double) GROUP_INDENT, + "y", (double) TITLE_HEIGHT, + NULL); + + /* + * Force dimension computation + */ + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update ( + GNOME_CANVAS_ITEM (etgc), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); +#endif +} + +ETableGroup * +e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules) +{ + ETableGroupContainer *etgc; + + g_return_val_if_fail (parent != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); + + etgc = gtk_type_new (e_table_group_container_get_type ()); + + e_table_group_container_construct (parent, etgc, full_header, header, + model, ecol, child_rules); + return E_TABLE_GROUP (etgc); +} + +#if 0 +static void +etgc_relayout (GnomeCanvasItem *eti, ETableGroupContainer *etgc) +{ + GList *l; + int height = etgc->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + if (child == eti) + move = TRUE; + + if (move){ + printf ("Moving item %p\n", child); + gnome_canvas_item_set ( child, + "y", (double) height, + NULL); + } + } + if (height != etgc->height){ + etgc->height = height; + gtk_signal_emit (GTK_OBJECT (etgc), etgc_signals [RESIZE]); + } +} + +void +e_table_group_container_add (ETableGroupContainer *etgc, GnomeCanvasItem *item) +{ + double x1, y1, x2, y2; + + g_return_if_fail (etgc != NULL); + g_return_if_fail (item != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etgc)); + g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); + + etgc->children = g_list_append (etgc->children, item); + + GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etgc)->klass)->bounds (etgc, &x1, &y1, &x2, &y2); + + if (GTK_OBJECT (etgc)->flags & GNOME_CANVAS_ITEM_REALIZED){ + GList *l; + int height = etgc->transparent ? 0 : TITLE_HEIGHT; + int x = etgc->transparent ? 0 : GROUP_INDENT; + + for (l = etgc->children; l->next; l = l->next){ + GnomeCanvasItem *child = l->data; + + height += child->y2 - child->y1; + + printf ("Height\n"); + if (E_IS_TABLE_ITEM (item)){ + printf (" Item: "); + } else { + printf (" Group: "); + } + printf ("%d\n", child->y2-child->y1); + } + + e_canvas_item_move_absolute ( item, x, height); + + + if (E_IS_TABLE_ITEM (item)){ + + printf ("Table item! ---------\n"); + gtk_signal_connect (GTK_OBJECT (item), "resize", + GTK_SIGNAL_FUNC (etgc_relayout), etgc); + } + } +} + +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + GList *l; + int height = 0; + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->realize (item); + + for (l = etgc->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; + + printf ("During realization for child %p -> %d\n", child, height); + gnome_canvas_item_set ( + child, + "y", (double) height, + NULL); + + height += child->y2 - child->y1; + } +} + +static void +etgc_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (item); + + GNOME_CANVAS_ITEM_CLASS (etgc_parent_class)->update (item, affine, clip_path, flags); + + if ( etgc->need_resize ) { + + if (!etgc->transparent){ + int current_width, current_height; + + etgc_dim (etgc, ¤t_width, ¤t_height); + + if ((current_height != etgc->height) || (current_width != etgc->width)){ + etgc->width = current_width; + etgc->height = current_height; + + gnome_canvas_item_set ( + etgc->rect, + "x1", 0.0, + "y1", 0.0, + "x2", (double) etgc->width, + "y2", (double) etgc->height, + NULL); + } + } + etgc->need_resize = FALSE; + } +} +#endif + +static int +etgc_event (GnomeCanvasItem *item, GdkEvent *event) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(item); + gboolean return_val = TRUE; + gboolean change_focus = FALSE; + gboolean use_col = FALSE; + gint start_col = 0; + gint old_col; + EFocus direction = E_FOCUS_START; + + switch (event->type) { + case GDK_KEY_PRESS: + if (event->key.keyval == GDK_Tab || + event->key.keyval == GDK_KP_Tab || + event->key.keyval == GDK_ISO_Left_Tab) { + change_focus = TRUE; + use_col = TRUE; + start_col = (event->key.state & GDK_SHIFT_MASK) ? -1 : 0; + direction = (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START; + } else if (event->key.keyval == GDK_Left || + event->key.keyval == GDK_KP_Left) { + change_focus = TRUE; + use_col = TRUE; + start_col = -1; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Right || + event->key.keyval == GDK_KP_Right) { + change_focus = TRUE; + use_col = TRUE; + start_col = 0; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Down || + event->key.keyval == GDK_KP_Down) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } else if (event->key.keyval == GDK_Up || + event->key.keyval == GDK_KP_Up) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_END; + } else if (event->key.keyval == GDK_Return || + event->key.keyval == GDK_KP_Enter) { + change_focus = TRUE; + use_col = FALSE; + direction = E_FOCUS_START; + } + if ( change_focus ) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + old_col = e_table_group_get_focus_column(child); + + if (direction == E_FOCUS_END) + list = list->prev; + else + list = list->next; + + if (list) { + child_node = (ETableGroupContainerChildNode *)list->data; + child = child_node->child; + if (use_col) + e_table_group_set_focus(child, direction, start_col); + else { + e_table_group_set_focus(child, direction, old_col); + } + return 1; + } else { + return 0; + } + } + } + } + return_val = FALSE; + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->event(item, event); + } + return return_val; + +} + +/* Realize handler for the text item */ +static void +etgc_realize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->realize) (item); + + etgc = E_TABLE_GROUP_CONTAINER (item); +} + +/* Unrealize handler for the etgc item */ +static void +etgc_unrealize (GnomeCanvasItem *item) +{ + ETableGroupContainer *etgc; + + etgc = E_TABLE_GROUP_CONTAINER (item); + + etgc->font = NULL; + + if (GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) + (* GNOME_CANVAS_ITEM_CLASS(etgc_parent_class)->unrealize) (item); +} + +static void +compute_text (ETableGroupContainer *etgc, ETableGroupContainerChildNode *child_node) +{ + /* FIXME : What a hack, eh? */ + gchar *text = g_strdup_printf("%s : %s (%d items)", etgc->ecol->text, (gchar *)child_node->key, (gint) child_node->count); + gnome_canvas_item_set(child_node->text, + "text", text, + NULL); + g_free(text); +} + +static void etgc_add (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + void *val = e_table_model_value_at (etg->model, etgc->ecol->col_idx, row); + GCompareFunc comp = etgc->ecol->compare; + GList *list = etgc->children; + ETableGroup *child; + ETableGroupContainerChildNode *child_node; + for ( ; list; list = g_list_next(list) ) { + child_node = (ETableGroupContainerChildNode *)(list->data); + if ( (*comp)(child_node->key, val) ) { + child = child_node->child; + child_node->count ++; + e_table_group_add(child, row); + compute_text(etgc, child_node); + return; + } + } + child_node = g_new(ETableGroupContainerChildNode, 1); + child_node->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + gnome_canvas_rect_get_type (), + "fill_color", "grey70", + "outline_color", "grey50", + NULL); + child_node->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgc), + e_text_get_type(), + "font_gdk", etgc->font, + "anchor", GTK_ANCHOR_SW, + "x", (double) 0, + "y", (double) 0, + "fill_color", "black", + NULL); + child = e_table_group_new(GNOME_CANVAS_GROUP(etgc), etg->full_header, etg->header, etg->model, etgc->child_rules); + child_node->child = child; + child_node->key = val; + + gtk_signal_connect(GTK_OBJECT(child), "resize", + etgc_child_resize, etgc); + child_node->count = 1; + e_table_group_add(child, row); + etgc->children = g_list_append(etgc->children, child_node); + compute_text(etgc, child_node); + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gboolean etgc_remove (ETableGroup *etg, gint row) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + if ( e_table_group_remove(child, row) ) { + child_node->count --; + if ( child_node->count == 0 ) { + gtk_object_unref(GTK_OBJECT(child_node->text)); + gtk_object_unref(GTK_OBJECT(child)); + etgc->children = g_list_remove(etgc->children, child_node); + g_free(child_node); + } else { + compute_text(etgc, child_node); + } + return TRUE; + } + } + return FALSE; + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + GList *list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + e_table_group_increment(((ETableGroupContainerChildNode *)list->data)->child, position, amount); + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void etgc_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + if (direction == E_FOCUS_END) { + e_table_group_set_focus(((ETableGroupContainerChildNode *)g_list_last(etgc->children)->data)->child, direction, view_col); + } else { + e_table_group_set_focus(((ETableGroupContainerChildNode *)etgc->children->data)->child, direction, view_col); + } + } + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gint +etgc_get_focus_column (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(etg); + if (etgc->children) { + GList *list; + for (list = etgc->children; list; list = list->next) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *)list->data; + ETableGroup *child = child_node->child; + if (e_table_group_get_focus(child)) { + return e_table_group_get_focus_column(child); + } + } + } + return 0; +} + +static void etgc_thaw (ETableGroup *etg) +{ + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static void +etgc_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etgc_thaw(etg); + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgc_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void etgc_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + GList *list = etgc->children; + etgc->width = width; + + for ( ; list; list = g_list_next(list) ) { + gdouble child_width = width - GROUP_INDENT; + gtk_object_set(GTK_OBJECT(((ETableGroupContainerChildNode *)list->data)->child), + "width", child_width, + NULL); + } + + etgc_queue_reposition(E_TABLE_GROUP_CONTAINER(etg)); +} + +static gdouble etgc_get_width (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->width; +} + +static gdouble etgc_get_height (ETableGroup *etg) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER (etg); + return etgc->height; +} + +static void +etgc_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgc_destroy; + object_class->set_arg = etgc_set_arg; + object_class->get_arg = etgc_get_arg; + + item_class->event = etgc_event; + item_class->realize = etgc_realize; + item_class->unrealize = etgc_unrealize; + + etgc_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgc_add; + e_group_class->remove = etgc_remove; + e_group_class->increment = etgc_increment; + e_group_class->set_focus = etgc_set_focus; + e_group_class->get_focus_column = etgc_get_focus_column; + e_group_class->thaw = etgc_thaw; + + e_group_class->get_width = etgc_get_width; + e_group_class->set_width = etgc_set_width; + e_group_class->get_height = etgc_get_height; + + gtk_object_add_arg_type ("ETableGroupContainer::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupContainer::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupContainer::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgc_init (GtkObject *object) +{ + ETableGroupContainer *container = E_TABLE_GROUP_CONTAINER(object); + container->children = FALSE; +} + +static gboolean +etgc_update_positioning (ETableGroupContainer *etgc, gpointer data) +{ + gboolean frozen; + gtk_object_get(GTK_OBJECT(etgc), + "frozen", &frozen, + NULL); + if ( frozen ) { + etgc->idle = 0; + return FALSE; + } + if ( GTK_OBJECT_FLAGS( etgc ) & GNOME_CANVAS_ITEM_REALIZED ) { + gdouble old_height; + + old_height = etgc->height; + if ( etgc->children == NULL ) { + } else { + GList *list; + gdouble extra_height; + gdouble running_height; + gdouble item_height = 0; + + extra_height = 0; + if (etgc->font) + extra_height += etgc->font->ascent + etgc->font->descent + BUTTON_PADDING * 2; + + extra_height = MAX(extra_height, BUTTON_HEIGHT + BUTTON_PADDING * 2); + + running_height = extra_height; + + list = etgc->children; + for ( ; list; list = g_list_next(list) ) { + ETableGroupContainerChildNode *child_node = (ETableGroupContainerChildNode *) list->data; + ETableGroup *child = child_node->child; + gtk_object_get( GTK_OBJECT(child), + "height", &item_height, + NULL ); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child_node->text), + GROUP_INDENT, + running_height - BUTTON_PADDING); + + e_canvas_item_move_absolute(GNOME_CANVAS_ITEM(child), + GROUP_INDENT, + running_height); + + gnome_canvas_item_set(GNOME_CANVAS_ITEM(child_node->rect), + "x1", (double) 0, + "x2", (double) etgc->width, + "y1", (double) running_height - extra_height, + "y2", (double) running_height + item_height, + NULL); + + running_height += item_height + extra_height; + } + running_height -= extra_height; + if ( running_height != old_height) { + etgc->height = running_height; + gtk_signal_emit_by_name (GTK_OBJECT (etgc), "resize"); + } + } + } + etgc->idle = 0; + return FALSE; +} + +static void +etgc_queue_reposition (ETableGroupContainer *etgc) +{ + if (etgc->idle == 0) + etgc->idle = g_idle_add((GSourceFunc)etgc_update_positioning, etgc); +} + +static void +etgc_child_resize (GtkObject *object, gpointer data) +{ + ETableGroupContainer *etgc = E_TABLE_GROUP_CONTAINER(data); + etgc_queue_reposition (etgc); +} + +E_MAKE_TYPE (e_table_group_container, "ETableGroupContainer", ETableGroupContainer, etgc_class_init, etgc_init, PARENT_TYPE); + diff --git a/widgets/e-table/e-table-group-container.h b/widgets/e-table/e-table-group-container.h new file mode 100644 index 0000000000..4942f9e695 --- /dev/null +++ b/widgets/e-table/e-table-group-container.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_CONTAINER_H_ +#define _E_TABLE_GROUP_CONTAINER_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-model.h" +#include "e-table-header.h" +#include "e-table-group.h" + +#define E_TABLE_GROUP_CONTAINER_TYPE (e_table_group_container_get_type ()) +#define E_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainer)) +#define E_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_CONTAINER_TYPE, ETableGroupContainerClass)) +#define E_IS_TABLE_GROUP_CONTAINER(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_CONTAINER_TYPE)) +#define E_IS_TABLE_GROUP_CONTAINER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_CONTAINER_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * The ETableCol used to group this set + */ + ETableCol *ecol; + + /* + * List of ETableGroups we stack + */ + GList *children; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + GdkFont *font; + + gdouble width, height; + + void *child_rules; + + gint idle; + + /* + * Update booleans: + */ + guint need_resize : 1; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; +} ETableGroupContainer; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupContainerClass; + +ETableGroup *e_table_group_container_new (GnomeCanvasGroup *parent, ETableHeader *full_header, ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); +void e_table_group_container_construct (GnomeCanvasGroup *parent, ETableGroupContainer *etgc, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, ETableCol *ecol, xmlNode *child_rules); + +GtkType e_table_group_container_get_type (void); + +#endif /* _E_TABLE_GROUP_CONTAINER_H_ */ diff --git a/widgets/e-table/e-table-group-leaf.c b/widgets/e-table/e-table-group-leaf.c new file mode 100644 index 0000000000..ba73ad9886 --- /dev/null +++ b/widgets/e-table/e-table-group-leaf.c @@ -0,0 +1,288 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-Table-Group.c: Implements the grouping objects for elements on a table + * + * Author: + * Miguel de Icaza (miguel@gnu.org() + * + * Copyright 1999, Helix Code, Inc. + */ + +#include <config.h> +#include <gtk/gtksignal.h> +#include "e-table-group-leaf.h" +#include "e-table-item.h" +#include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include "e-util/e-util.h" + +#define TITLE_HEIGHT 16 +#define GROUP_INDENT 10 + +#define PARENT_TYPE e_table_group_get_type () + +static GnomeCanvasGroupClass *etgl_parent_class; + +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; + +static void etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static void +etgl_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (etgl_parent_class)->destroy (object); +} + +static void +e_table_group_leaf_construct (GnomeCanvasGroup *parent, ETableGroupLeaf *etgl, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + e_table_group_construct (parent, E_TABLE_GROUP (etgl), full_header, header, model); + etgl->subset = E_TABLE_SUBSET_VARIABLE(e_table_subset_variable_new(model)); +} + +ETableGroup * +e_table_group_leaf_new (GnomeCanvasGroup *parent, ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + ETableGroupLeaf *etgl; + + g_return_val_if_fail (parent != NULL, NULL); + + etgl = gtk_type_new (e_table_group_leaf_get_type ()); + + e_table_group_leaf_construct (parent, etgl, full_header, + header, model); + return E_TABLE_GROUP (etgl); +} + +static void +etgl_resize (GtkObject *object, gpointer data) +{ + e_table_group_resize (E_TABLE_GROUP(data)); +} + +static void +etgl_realize (GnomeCanvasItem *item) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF(item); + gdouble height; + + if ( GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize ) + GNOME_CANVAS_ITEM_CLASS (etgl_parent_class)->realize (item); + + etgl->item = E_TABLE_ITEM(gnome_canvas_item_new(GNOME_CANVAS_GROUP(etgl), + e_table_item_get_type (), + "ETableHeader", E_TABLE_GROUP(etgl)->header, + "ETableModel", etgl->subset, + "drawgrid", TRUE, + "drawfocus", TRUE, + "spreadsheet", TRUE, + "width", etgl->width, + NULL)); + gtk_signal_connect(GTK_OBJECT(etgl->item), + "resize", etgl_resize, etgl); + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + if ( height != 1 ) + e_table_group_resize(E_TABLE_GROUP(etgl)); +} + +static int +etgl_event (GnomeCanvasItem *item, GdkEvent *event) +{ + gboolean return_val = TRUE; + + switch (event->type) { + + default: + return_val = FALSE; + } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etgl_parent_class)->event(item, event); + } + return return_val; + +} + +static void +etgl_add (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_add(etgl->subset, row); +} + +static gboolean +etgl_remove (ETableGroup *etg, gint row) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_subset_variable_remove(etgl->subset, row); +} + +static void +etgl_increment (ETableGroup *etg, gint position, gint amount) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + e_table_subset_variable_increment(etgl->subset, position, amount); +} + +static void +etgl_set_focus (ETableGroup *etg, EFocus direction, gint view_col) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + if (direction == E_FOCUS_END) { + e_table_item_focus(etgl->item, view_col, e_table_model_row_count(E_TABLE_MODEL(etgl->subset)) - 1); + } else { + e_table_item_focus(etgl->item, view_col, 0); + } +} + +static gint +etgl_get_focus_column (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + return e_table_item_get_focused_column(etgl->item); +} + +static void +etgl_set_width (ETableGroup *etg, gdouble width) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + etgl->width = width; +#if 0 + if ( etgl->item ) { + gnome_canvas_item_set(GNOME_CANVAS_ITEM(etgl->item), + "width", width, + NULL); + } +#endif +} + +static gdouble +etgl_get_width (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gtk_object_get(GTK_OBJECT(etgl->item), + "width", &etgl->width, + NULL); + return etgl->width; +} + +static gdouble +etgl_get_height (ETableGroup *etg) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (etg); + gdouble height; + if ( etgl->item ) + gtk_object_get(GTK_OBJECT(etgl->item), + "height", &height, + NULL); + else + height = 1; + return height; +} + +static void +etgl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + } + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width ) + E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; + } +} + +static void +etgl_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width ) + GTK_VALUE_DOUBLE (*arg) = E_TABLE_GROUP_CLASS(GTK_OBJECT(etg)->klass)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +etgl_class_init (GtkObjectClass *object_class) +{ + GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *e_group_class = E_TABLE_GROUP_CLASS( object_class ); + + object_class->destroy = etgl_destroy; + object_class->set_arg = etgl_set_arg; + object_class->get_arg = etgl_get_arg; + + item_class->realize = etgl_realize; + item_class->event = etgl_event; + + etgl_parent_class = gtk_type_class (PARENT_TYPE); + + e_group_class->add = etgl_add; + e_group_class->remove = etgl_remove; + e_group_class->increment = etgl_increment; + e_group_class->set_focus = etgl_set_focus; + e_group_class->get_focus_column = etgl_get_focus_column; + + e_group_class->get_width = etgl_get_width; + e_group_class->set_width = etgl_set_width; + e_group_class->get_height = etgl_get_height; + + gtk_object_add_arg_type ("ETableGroupLeaf::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableGroupLeaf::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableGroupLeaf::frozen", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_FROZEN); +} + +static void +etgl_init (GtkObject *object) +{ + ETableGroupLeaf *etgl = E_TABLE_GROUP_LEAF (object); + + etgl->width = 1; + etgl->subset = NULL; + etgl->item = NULL; +} + +E_MAKE_TYPE (e_table_group_leaf, "ETableGroupLeaf", ETableGroupLeaf, etgl_class_init, etgl_init, PARENT_TYPE); diff --git a/widgets/e-table/e-table-group-leaf.h b/widgets/e-table/e-table-group-leaf.h new file mode 100644 index 0000000000..372bf4cc70 --- /dev/null +++ b/widgets/e-table/e-table-group-leaf.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_LEAF_H_ +#define _E_TABLE_GROUP_LEAF_H_ + +#include <libgnomeui/gnome-canvas.h> +#include "e-table-group.h" +#include "e-table-subset-variable.h" +#include "e-table-item.h" + +#define E_TABLE_GROUP_LEAF_TYPE (e_table_group_leaf_get_type ()) +#define E_TABLE_GROUP_LEAF(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeaf)) +#define E_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_LEAF_TYPE, ETableGroupLeafClass)) +#define E_IS_TABLE_GROUP_LEAF(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_LEAF_TYPE)) +#define E_IS_TABLE_GROUP_LEAF_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_LEAF_TYPE)) + +typedef struct { + ETableGroup group; + + /* + * Item. + */ + ETableItem *item; + + gdouble width; + + ETableSubsetVariable *subset; +} ETableGroupLeaf; + +typedef struct { + ETableGroupClass parent_class; +} ETableGroupLeafClass; + +ETableGroup *e_table_group_leaf_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); +GtkType e_table_group_leaf_get_type (void); + +#endif /* _E_TABLE_GROUP_LEAF_H_ */ diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c index 5652d2623f..68bc3e7abf 100644 --- a/widgets/e-table/e-table-group.c +++ b/widgets/e-table/e-table-group.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-Table-Group.c: Implements the grouping objects for elements on a table * @@ -10,8 +11,11 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-group-container.h" +#include "e-table-group-leaf.h" #include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" #define TITLE_HEIGHT 16 @@ -19,88 +23,30 @@ #define PARENT_TYPE gnome_canvas_group_get_type () +#define ETG_CLASS(e) (E_TABLE_GROUP_CLASS(GTK_OBJECT(e)->klass)) + static GnomeCanvasGroupClass *etg_parent_class; enum { - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; static gint etg_signals [LAST_SIGNAL] = { 0, }; -static void -etg_destroy (GtkObject *object) -{ - ETableGroup *etg = E_TABLE_GROUP (object); - - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); -} - -static void -etg_dim (ETableGroup *etg, int *width, int *height) -{ - GSList *l; - - *width = *height = 0; - - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; - - *height += child->y2 - child->y1; - *width += child->x2 - child->x1; - } - - if (!etg->transparent){ - *height += TITLE_HEIGHT; - *width += GROUP_INDENT; - } -} +/* The arguments we take */ +enum { + ARG_0, + ARG_HEIGHT, + ARG_WIDTH, + ARG_FROZEN +}; -void -e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, - gboolean transparent) -{ - gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - - etg->ecol = ecol; - etg->open = open; - etg->transparent = transparent; - - etg_dim (etg, &etg->width, &etg->height); - - if (!etg->transparent) - etg->rect = gnome_canvas_item_new ( - GNOME_CANVAS_GROUP (etg), - gnome_canvas_rect_get_type (), - "fill_color", "gray", - "outline_color", "gray20", - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); +static void etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static gboolean etg_get_focus (ETableGroup *etg); #if 0 - /* - * Reparent the child into our space. - */ - gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etg)); - - gnome_canvas_item_set ( - child, - "x", (double) GROUP_INDENT, - "y", (double) TITLE_HEIGHT, - NULL); - - /* - * Force dimension computation - */ - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update ( - GNOME_CANVAS_ITEM (etg), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED); -#endif -} - GnomeCanvasItem * e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, gboolean open, gboolean transparent) @@ -116,158 +62,275 @@ e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, return GNOME_CANVAS_ITEM (etg); } +#endif -static void -etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +ETableGroup * +e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules) { - GSList *l; - int height = etg->transparent ? 0 : GROUP_INDENT; - gboolean move = FALSE; + g_return_val_if_fail (model != NULL, NULL); - printf ("Relaying out\n"); - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; + if(rules && !xmlStrcmp(rules->name, "group")) { + gint col_idx = atoi(xmlGetProp(rules, "column")); + ETableCol *col; + if ( col_idx > e_table_header_count(full_header) ) + return e_table_group_leaf_new(parent, full_header, header, model); + col = e_table_header_get_columns(full_header)[col_idx]; + return e_table_group_container_new(parent, full_header, header, model, col, rules->childs); + } else { + return e_table_group_leaf_new(parent, full_header, header, model); + } + return NULL; +} + +void +e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model) +{ + gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); + etg->full_header = full_header; + etg->header = header; + etg->model = model; +} + +void +e_table_group_add (ETableGroup *etg, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); - height += child->y2 - child->y1; + if ( ETG_CLASS (etg)->add ) + ETG_CLASS (etg)->add (etg, row); +} - if (child == eti) - move = TRUE; +gboolean +e_table_group_remove (ETableGroup *etg, + gint row) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); - if (move){ - printf ("Moving item %p\n", child); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); - } - } - if (height != etg->height){ - etg->height = height; - gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); - } + if ( ETG_CLASS (etg)->remove ) + return ETG_CLASS (etg)->remove (etg, row); + else + return FALSE; +} + +gint +e_table_group_get_count (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, 0); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), 0); + + if ( ETG_CLASS (etg)->get_count ) + return ETG_CLASS (etg)->get_count (etg); + else + return 0; } void -e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item) +e_table_group_increment (ETableGroup *etg, + gint position, + gint amount) { - double x1, y1, x2, y2; - g_return_if_fail (etg != NULL); - g_return_if_fail (item != NULL); g_return_if_fail (E_IS_TABLE_GROUP (etg)); - g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); - - etg->children = g_slist_append (etg->children, item); - - GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2); - - if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){ - GSList *l; - int height = etg->transparent ? 0 : TITLE_HEIGHT; - int x = etg->transparent ? 0 : GROUP_INDENT; - - for (l = etg->children; l->next; l = l->next){ - GnomeCanvasItem *child = l->data; - - height += child->y2 - child->y1; - - printf ("Height\n"); - if (E_IS_TABLE_ITEM (item)){ - printf (" Item: "); - } else { - printf (" Group: "); - } - printf ("%d\n", child->y2-child->y1); - } - gnome_canvas_item_set ( - item, - "y", (double) height, - "x", (double) x, - NULL); - - - if (E_IS_TABLE_ITEM (item)){ - - printf ("Table item! ---------\n"); - gtk_signal_connect (GTK_OBJECT (item), "height_changed", - GTK_SIGNAL_FUNC (etg_relayout), etg); - } - } + if ( ETG_CLASS (etg)->increment ) + ETG_CLASS (etg)->increment (etg, position, amount); } -static void -etg_realize (GnomeCanvasItem *item) +void +e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint row) +{ + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->set_focus ) + ETG_CLASS (etg)->set_focus (etg, direction, row); +} + +gboolean +e_table_group_get_focus (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus ) + return ETG_CLASS (etg)->get_focus (etg); + else + return FALSE; +} + +gboolean +e_table_group_get_focus_column (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, FALSE); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), FALSE); + + if ( ETG_CLASS (etg)->get_focus_column ) + return ETG_CLASS (etg)->get_focus_column (etg); + else + return FALSE; +} + +ETableCol * +e_table_group_get_ecol (ETableGroup *etg) +{ + g_return_val_if_fail (etg != NULL, NULL); + g_return_val_if_fail (E_IS_TABLE_GROUP (etg), NULL); + + if ( ETG_CLASS (etg)->get_ecol ) + return ETG_CLASS (etg)->get_ecol (etg); + else + return NULL; +} + +void +e_table_group_resize (ETableGroup *e_table_group) +{ + g_return_if_fail (e_table_group != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (e_table_group)); + + gtk_signal_emit (GTK_OBJECT (e_table_group), + etg_signals [RESIZE]); +} + +static int +etg_event (GnomeCanvasItem *item, GdkEvent *event) { ETableGroup *etg = E_TABLE_GROUP (item); - GSList *l; - int height = 0; - - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item); + gboolean return_val = TRUE; - for (l = etg->children; l; l = l->next){ - GnomeCanvasItem *child = l->data; + switch (event->type) { - printf ("During realization for child %p -> %d\n", child, height); - gnome_canvas_item_set ( - child, - "y", (double) height, - NULL); + case GDK_FOCUS_CHANGE: + etg->has_focus = event->focus_change.in; + return_val = FALSE; - height += child->y2 - child->y1; + default: + return_val = FALSE; } + if ( return_val == FALSE ) { + if ( GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event ) + return GNOME_CANVAS_ITEM_CLASS(etg_parent_class)->event(item, event); + } + return return_val; + } static void -etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +etg_thaw(ETableGroup *etg) { - ETableGroup *etg = E_TABLE_GROUP (item); + g_return_if_fail (etg != NULL); + g_return_if_fail (E_IS_TABLE_GROUP (etg)); + + if ( ETG_CLASS (etg)->thaw ) + ETG_CLASS (etg)->thaw (etg); +} + +static void +etg_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); - GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags); - - if (!etg->transparent){ - int current_width, current_height; - - etg_dim (etg, ¤t_width, ¤t_height); - - if ((current_height != etg->height) || (current_width != etg->width)){ - etg->width = current_width; - etg->height = current_height; - - gnome_canvas_item_set ( - etg->rect, - "x1", 0.0, - "y1", 0.0, - "x2", (double) etg->width, - "y2", (double) etg->height, - NULL); + switch (arg_id) { + case ARG_FROZEN: + if ( GTK_VALUE_BOOL (*arg) ) + etg->frozen = TRUE; + else { + etg->frozen = FALSE; + etg_thaw(etg); } + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->set_width ) + ETG_CLASS(etg)->set_width(etg, GTK_VALUE_DOUBLE (*arg)); + break; + default: + break; } } static void +etg_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + ETableGroup *etg = E_TABLE_GROUP (object); + + switch (arg_id) { + case ARG_FROZEN: + GTK_VALUE_BOOL (*arg) = etg->frozen; + break; + case ARG_HEIGHT: + if ( ETG_CLASS(etg)->get_height ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_height(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + case ARG_WIDTH: + if ( ETG_CLASS(etg)->get_width ) + GTK_VALUE_DOUBLE (*arg) = ETG_CLASS(etg)->get_width(etg); + else + arg->type = GTK_TYPE_INVALID; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static gboolean +etg_get_focus (ETableGroup *etg) +{ + return etg->has_focus; +} + +static void etg_class_init (GtkObjectClass *object_class) { GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class; + ETableGroupClass *klass = (ETableGroupClass *) object_class; + + object_class->set_arg = etg_set_arg; + object_class->get_arg = etg_get_arg; - object_class->destroy = etg_destroy; + item_class->event = etg_event; - item_class->realize = etg_realize; - item_class->update = etg_update; + klass->resize = NULL; + + klass->add = NULL; + klass->remove = NULL; + klass->get_count = NULL; + klass->increment = NULL; + klass->set_focus = NULL; + klass->get_focus = etg_get_focus; + klass->get_ecol = NULL; + + klass->thaw = NULL; + klass->get_height = NULL; + klass->get_width = NULL; + klass->set_width = NULL; etg_parent_class = gtk_type_class (PARENT_TYPE); - etg_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + etg_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + GTK_SIGNAL_OFFSET (ETableGroupClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, etg_signals, LAST_SIGNAL); - } E_MAKE_TYPE (e_table_group, "ETableGroup", ETableGroup, etg_class_init, NULL, PARENT_TYPE); diff --git a/widgets/e-table/e-table-group.h b/widgets/e-table/e-table-group.h index 468d5dd794..1b3f346290 100644 --- a/widgets/e-table/e-table-group.h +++ b/widgets/e-table/e-table-group.h @@ -1,9 +1,12 @@ -#ifndef _E_TABLE_TREE_H_ -#define _E_TABLE_TREE_H_ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_GROUP_H_ +#define _E_TABLE_GROUP_H_ #include <libgnomeui/gnome-canvas.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-util/e-util.h" #define E_TABLE_GROUP_TYPE (e_table_group_get_type ()) #define E_TABLE_GROUP(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_TYPE, ETableGroup)) @@ -15,49 +18,75 @@ typedef struct { GnomeCanvasGroup group; /* - * The ETableCol used to group this set + * The full header. */ - ETableCol *ecol; - - /* - * The canvas rectangle that contains the children - */ - GnomeCanvasItem *rect; - - /* - * Dimensions of the ETableGroup - */ - int width, height; - + ETableHeader *full_header; + ETableHeader *header; + /* - * State: the ETableGroup is open or closed + * The model we pull data from. */ - guint open:1; + ETableModel *model; /* * Whether we should add indentation and open/close markers, * or if we just act as containers of subtables. */ - guint transparent:1; + guint transparent : 1; - /* - * List of GnomeCanvasItems we stack - */ - GSList *children; + guint has_focus : 1; + + guint frozen : 1; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; - void (*height_changed) (ETableGroup *etg); + void (*resize) (ETableGroup *etg); + + void (*add) (ETableGroup *etg, gint row); + gboolean (*remove) (ETableGroup *etg, gint row); + gint (*get_count) (ETableGroup *etg); + void (*increment) (ETableGroup *etg, gint position, gint amount); + void (*set_focus) (ETableGroup *etg, EFocus direction, gint view_col); + gboolean (*get_focus) (ETableGroup *etg); + gint (*get_focus_column) (ETableGroup *etg); + ETableCol *(*get_ecol) (ETableGroup *etg); + + void (*thaw) (ETableGroup *etg); + gdouble (*get_height) (ETableGroup *etg); + gdouble (*get_width) (ETableGroup *etg); + void (*set_width) (ETableGroup *etg, gdouble width); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, - gboolean open, gboolean transparent); -void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableCol *ecol, gboolean open, gboolean transparent); +void e_table_group_add (ETableGroup *etg, + gint row); +gboolean e_table_group_remove (ETableGroup *etg, + gint row); +gint e_table_group_get_count (ETableGroup *etg); +void e_table_group_increment (ETableGroup *etg, + gint position, + gint amount); +void e_table_group_set_focus (ETableGroup *etg, + EFocus direction, + gint view_col); +gboolean e_table_group_get_focus (ETableGroup *etg); +gint e_table_group_get_focus_column (ETableGroup *etg); +ETableCol *e_table_group_get_ecol (ETableGroup *etg); + +ETableGroup *e_table_group_new (GnomeCanvasGroup *parent, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model, + xmlNode *rules); +void e_table_group_construct (GnomeCanvasGroup *parent, + ETableGroup *etg, + ETableHeader *full_header, + ETableHeader *header, + ETableModel *model); -void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); +/* For emitting the signal */ +void e_table_group_resize (ETableGroup *etg); GtkType e_table_group_get_type (void); -#endif /* _E_TABLE_TREE_H_ */ +#endif /* _E_TABLE_GROUP_H_ */ diff --git a/widgets/e-table/e-table-header-item.c b/widgets/e-table/e-table-header-item.c index b025664385..6b6146c938 100644 --- a/widgets/e-table/e-table-header-item.c +++ b/widgets/e-table/e-table-header-item.c @@ -317,7 +317,7 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context, { /* Check if it's the correct ethi */ if (ethi->drag_col == -1) - return; + return FALSE; gdk_drag_status (context, 0, time); if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { @@ -372,7 +372,7 @@ ethi_drag_drop (GtkWidget *canvas, gboolean successful = FALSE; if (ethi->drag_col == -1) - return; + return FALSE; if (GTK_WIDGET(canvas) == gtk_drag_get_source_widget(context)) { if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) && @@ -486,7 +486,6 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, { GdkRectangle clip; int xtra; - int arrowx; gdk_draw_rectangle ( drawable, gc, TRUE, @@ -541,7 +540,7 @@ draw_button (ETableHeaderItem *ethi, ETableCol *col, gtk_paint_arrow (gtk_widget_get_style(GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas)), drawable, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, + GTK_SHADOW_IN, &clip, GTK_WIDGET(GNOME_CANVAS_ITEM(ethi)->canvas), "header", diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index 130c51a85c..d8ecdf1404 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel. * @@ -26,7 +27,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, - HEIGHT_CHANGED, + RESIZE, LAST_SIGNAL }; @@ -36,12 +37,14 @@ enum { ARG_0, ARG_TABLE_HEADER, ARG_TABLE_MODEL, - ARG_TABLE_X, - ARG_TABLE_Y, ARG_TABLE_DRAW_GRID, ARG_TABLE_DRAW_FOCUS, ARG_MODE_SPREADSHEET, - ARG_LENGHT_THRESHOLD + ARG_LENGHT_THRESHOLD, + + ARG_WIDTH, + ARG_HEIGHT, + ARG_HAS_FOCUS }; static gboolean @@ -67,7 +70,7 @@ eti_realize_cell_views (ETableItem *eti) int i; for (i = 0; i < eti->n_cells; i++) - e_cell_view_realize (eti->cell_views [i], eti); + e_cell_realize (eti->cell_views [i]); eti->cell_views_realized = 1; } @@ -287,13 +290,13 @@ eti_compute_height (ETableItem *eti) int new_height = eti_get_height (eti); if (new_height != eti->height){ - double x1, y1, x2, y2; + /* double x1, y1, x2, y2;*/ printf ("Emitting!\n"); eti->height = new_height; eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); - gtk_signal_emit (GTK_OBJECT (eti), eti_signals [HEIGHT_CHANGED]); + gtk_signal_emit (GTK_OBJECT (eti), eti_signals [RESIZE]); } } @@ -537,14 +540,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) eti_add_table_model (eti, GTK_VALUE_POINTER (*arg)); break; - case ARG_TABLE_X: - eti->x1 = GTK_VALUE_DOUBLE (*arg); - break; - - case ARG_TABLE_Y: - eti->y1 = GTK_VALUE_DOUBLE (*arg); - break; - case ARG_LENGHT_THRESHOLD: eti->length_threshold = GTK_VALUE_INT (*arg); break; @@ -565,6 +560,27 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) } static void +eti_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + ETableItem *eti; + + item = GNOME_CANVAS_ITEM (o); + eti = E_TABLE_ITEM (o); + + switch (arg_id){ + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = eti->width; + break; + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = eti->height; + break; + default: + arg->type = GTK_TYPE_INVALID; + } +} + +static void eti_init (GnomeCanvasItem *item) { ETableItem *eti = E_TABLE_ITEM (item); @@ -576,7 +592,7 @@ eti_init (GnomeCanvasItem *item) eti->height = 0; eti->length_threshold = -1; - eti->renderers_can_change_size = 0; + eti->renderers_can_change_size = 1; eti->selection_mode = GTK_SELECTION_SINGLE; } @@ -878,31 +894,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub } static void -eti_cursor_move_left (ETableItem *eti) +eti_cursor_move (ETableItem *eti, gint row, gint column) { e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); + e_table_item_focus (eti, column, row); +} + +static void +eti_cursor_move_left (ETableItem *eti) +{ + eti_cursor_move(eti, eti->focused_row, eti->focused_col - 1); } static void eti_cursor_move_right (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); + eti_cursor_move(eti, eti->focused_row, eti->focused_col + 1); } static void eti_cursor_move_up (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); + eti_cursor_move(eti, eti->focused_row - 1, eti->focused_col); } static void eti_cursor_move_down (ETableItem *eti) { - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); + eti_cursor_move(eti, eti->focused_row + 1, eti->focused_col); } static int @@ -911,6 +930,7 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) ETableItem *eti = E_TABLE_ITEM (item); ECellView *ecell_view; ETableCol *ecol; + gint return_val = TRUE; switch (e->type){ case GDK_BUTTON_PRESS: @@ -982,66 +1002,66 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (eti->focused_col > 0) eti_cursor_move_left (eti); - - return TRUE; - + break; + case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - return TRUE; - + break; + case GDK_Up: if (eti->focused_row > 0) eti_cursor_move_up (eti); - return TRUE; + else + return_val = FALSE; + break; case GDK_Down: if ((eti->focused_row + 1) < eti->rows) eti_cursor_move_down (eti); - - return TRUE; + else + return_val = FALSE; + break; case GDK_Tab: + case GDK_KP_Tab: + case GDK_ISO_Left_Tab: if ((e->key.state & GDK_SHIFT_MASK) != 0){ /* shift tab */ if (eti->focused_col > 0) eti_cursor_move_left (eti); - else if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->cols - 1, eti->focused_row - 1); - } else { - /* FIXME: request focus leave backward */ - } + else if (eti->focused_row > 0) + eti_cursor_move(eti, eti->focused_row - 1, eti->cols - 1); + else + return_val = FALSE; } else { - if ((eti->focused_col + 1) < eti->cols) + if (eti->focused_col < eti->cols - 1) eti_cursor_move_right (eti); - else if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, 0, eti->rows - 1); - } else { - /* FIXME: request focus leave forward */ - } + else if (eti->focused_row < eti->rows - 1) + eti_cursor_move(eti, eti->focused_row + 1, 0); + else + return_val = FALSE; } break; default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) - return 0; + return_val = FALSE; if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff)) - return 0; + return_val = FALSE; } - } - ecol = e_table_header_get_column (eti->header, eti->focused_col); - ecell_view = eti->cell_views [eti->focused_col]; - e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + ecol = e_table_header_get_column (eti->header, eti->focused_col); + ecell_view = eti->cell_views [eti->focused_col]; + e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row); + } break; - + case GDK_KEY_RELEASE: if (eti->focused_col == -1) return FALSE; @@ -1053,8 +1073,15 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) } break; + case GDK_FOCUS_CHANGE: + if (e->focus_change.in) { + } else { + e_table_item_leave_edit (eti); + e_table_item_unfocus (eti); + } + default: - return FALSE; + return_val = FALSE; } return TRUE; } @@ -1084,6 +1111,7 @@ eti_class_init (GtkObjectClass *object_class) object_class->destroy = eti_destroy; object_class->set_arg = eti_set_arg; + object_class->get_arg = eti_get_arg; item_class->update = eti_update; item_class->realize = eti_realize; @@ -1099,10 +1127,6 @@ eti_class_init (GtkObjectClass *object_class) GTK_ARG_WRITABLE, ARG_TABLE_HEADER); gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER, GTK_ARG_WRITABLE, ARG_TABLE_MODEL); - gtk_object_add_arg_type ("ETableItem::x", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_X); - gtk_object_add_arg_type ("ETableItem::y", GTK_TYPE_DOUBLE, - GTK_ARG_WRITABLE, ARG_TABLE_Y); gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID); gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL, @@ -1110,6 +1134,13 @@ eti_class_init (GtkObjectClass *object_class) gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET); + gtk_object_add_arg_type ("ETableItem::width", GTK_TYPE_DOUBLE, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("ETableItem::height", GTK_TYPE_DOUBLE, + GTK_ARG_READABLE, ARG_HEIGHT); + gtk_object_add_arg_type ("ETableItem::has_focus", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_HAS_FOCUS); + eti_signals [ROW_SELECTION] = gtk_signal_new ("row_selection", GTK_RUN_LAST, @@ -1118,11 +1149,11 @@ eti_class_init (GtkObjectClass *object_class) gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); - eti_signals [HEIGHT_CHANGED] = - gtk_signal_new ("height_changed", + eti_signals [RESIZE] = + gtk_signal_new ("resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + GTK_SIGNAL_OFFSET (ETableItemClass, resize), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); @@ -1192,6 +1223,16 @@ e_table_item_unfocus (ETableItem *eti) eti->focused_row = -1; } +gint +e_table_item_get_focused_column (ETableItem *eti) +{ + g_return_val_if_fail (eti != NULL, -1); + g_return_val_if_fail (E_IS_TABLE_ITEM (eti), -1); + + return eti->focused_col; +} + + const GSList * e_table_item_get_selection (ETableItem *eti) { diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index f19819f2fc..635dc76922 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -68,7 +68,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); - void (*height_changed) (ETableItem *eti); + void (*resize) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); @@ -79,6 +79,8 @@ GtkType e_table_item_get_type (void); void e_table_item_focus (ETableItem *eti, int col, int row); void e_table_item_unfocus (ETableItem *eti); +gint e_table_item_get_focused_column (ETableItem *eti); + /* * Selection */ diff --git a/widgets/e-table/e-table-model.c b/widgets/e-table/e-table-model.c index 9e397710ef..e84e6da4d3 100644 --- a/widgets/e-table/e-table-model.c +++ b/widgets/e-table/e-table-model.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a Table Model * @@ -173,4 +174,23 @@ e_table_model_cell_changed (ETableModel *e_table_model, int col, int row) e_table_model_signals [MODEL_CELL_CHANGED], col, row); } +void +e_table_model_freeze (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = TRUE; + return ETM_CLASS (e_table_model)->thaw (e_table_model); +} +void +e_table_model_thaw (ETableModel *e_table_model) +{ + g_return_if_fail (e_table_model != NULL); + g_return_if_fail (E_IS_TABLE_MODEL (e_table_model)); + + e_table_model->frozen = FALSE; + if (ETM_CLASS(e_table_model)->thaw) + ETM_CLASS (e_table_model)->thaw (e_table_model); +} diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h index 2d08f3744e..9f2dbbf87c 100644 --- a/widgets/e-table/e-table-model.h +++ b/widgets/e-table/e-table-model.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_MODEL_H_ #define _E_TABLE_MODEL_H_ @@ -11,6 +12,8 @@ typedef struct { GtkObject base; + + guint frozen : 1; } ETableModel; typedef struct { @@ -24,7 +27,7 @@ typedef struct { void *(*value_at) (ETableModel *etm, int col, int row); void (*set_value_at) (ETableModel *etm, int col, int row, const void *value); gboolean (*is_cell_editable) (ETableModel *etm, int col, int row); - + void (*thaw) (ETableModel *etm); /* * Signals */ @@ -48,6 +51,9 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col, void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data); gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row); +void e_table_model_freeze (ETableModel *e_table_model); +void e_table_model_thaw (ETableModel *e_table_model); + /* * Routines for emitting signals on the e_table */ diff --git a/widgets/e-table/e-table-simple.c b/widgets/e-table/e-table-simple.c index 38e1dd8eb0..1f64d08f39 100644 --- a/widgets/e-table/e-table-simple.c +++ b/widgets/e-table/e-table-simple.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * e-table-model.c: a simple table model implementation that uses function * pointers to simplify the creation of new, exotic and colorful tables in @@ -55,6 +56,14 @@ simple_is_cell_editable (ETableModel *etm, int col, int row) } static void +simple_thaw (ETableModel *etm) +{ + ETableSimple *simple = (ETableSimple *)etm; + + simple->thaw (etm, simple->data); +} + +static void e_table_simple_class_init (GtkObjectClass *object_class) { ETableModelClass *model_class = (ETableModelClass *) object_class; @@ -64,6 +73,7 @@ e_table_simple_class_init (GtkObjectClass *object_class) model_class->value_at = simple_value_at; model_class->set_value_at = simple_set_value_at; model_class->is_cell_editable = simple_is_cell_editable; + model_class->thaw = simple_thaw; } GtkType @@ -95,6 +105,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data) { ETableSimple *et; @@ -106,6 +117,7 @@ e_table_simple_new (ETableSimpleColumnCountFn col_count, et->value_at = value_at; et->set_value_at = set_value_at; et->is_cell_editable = is_cell_editable; + et->thaw = thaw; et->data = data; return (ETableModel *) et; diff --git a/widgets/e-table/e-table-simple.h b/widgets/e-table/e-table-simple.h index d890245386..a3164eefc0 100644 --- a/widgets/e-table/e-table-simple.h +++ b/widgets/e-table/e-table-simple.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SIMPLE_H_ #define _E_TABLE_SIMPLE_H_ @@ -8,6 +9,7 @@ typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *dat typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data); typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data); typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data); +typedef void (*ETableSimpleThawFn) (ETableModel *etm, void *data); typedef struct { ETableModel parent; @@ -17,6 +19,7 @@ typedef struct { ETableSimpleValueAtFn value_at; ETableSimpleSetValueAtFn set_value_at; ETableSimpleIsCellEditableFn is_cell_editable; + ETableSimpleThawFn thaw; void *data; } ETableSimple; @@ -31,6 +34,7 @@ ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count, ETableSimpleValueAtFn value_at, ETableSimpleSetValueAtFn set_value_at, ETableSimpleIsCellEditableFn is_cell_editable, + ETableSimpleThawFn thaw, void *data); #endif /* _E_TABLE_SIMPLE_H_ */ diff --git a/widgets/e-table/e-table-sorted.h b/widgets/e-table/e-table-sorted.h index 2ec52df2e7..92bd8d1522 100644 --- a/widgets/e-table/e-table-sorted.h +++ b/widgets/e-table/e-table-sorted.h @@ -19,7 +19,7 @@ typedef struct { } ETableSorted; typedef struct { - ETableSubset parent_class; + ETableSubsetClass parent_class; } ETableSortedClass; GtkType e_table_sorted_get_type (void); diff --git a/widgets/e-table/e-table-subset-variable.c b/widgets/e-table/e-table-subset-variable.c new file mode 100644 index 0000000000..76da03c44f --- /dev/null +++ b/widgets/e-table/e-table-subset-variable.c @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * E-table-subset.c: Implements a table that contains a subset of another table. + * + * Author: + * Miguel de Icaza (miguel@gnu.org) + * + * (C) 1999 Helix Code, Inc. + */ +#include <config.h> +#include <stdlib.h> +#include <gtk/gtksignal.h> +#include <string.h> +#include "e-util/e-util.h" +#include "e-table-subset-variable.h" + +#define PARENT_TYPE E_TABLE_SUBSET_TYPE + +#define INCREMENT_AMOUNT 10 + +static ETableModelClass *etssv_parent_class; + +static void +etssv_class_init (GtkObjectClass *klass) +{ + etssv_parent_class = gtk_type_class (PARENT_TYPE); +} + +E_MAKE_TYPE(e_table_subset_variable, "ETableSubsetVariable", ETableSubsetVariable, etssv_class_init, NULL, PARENT_TYPE); + +ETableModel * +e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source) +{ + if ( e_table_subset_construct(E_TABLE_SUBSET(etssv), source, 1) == NULL ) + return NULL; + E_TABLE_SUBSET(etssv)->n_map = 0; + + return E_TABLE_MODEL (etssv); +} + +ETableModel * +e_table_subset_variable_new (ETableModel *source) +{ + ETableSubsetVariable *etssv = gtk_type_new (E_TABLE_SUBSET_VARIABLE_TYPE); + + if (e_table_subset_variable_construct (etssv, source) == NULL){ + gtk_object_destroy (GTK_OBJECT (etssv)); + return NULL; + } + + return (ETableModel *) etssv; +} + +void +e_table_subset_variable_add (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + + if ( etss->n_map + 1 > etssv->n_vals_allocated ) + etss->map_table = g_realloc(etss->map_table, (etssv->n_vals_allocated + INCREMENT_AMOUNT) * sizeof(int)); + etss->map_table[etss->n_map++] = row; + if ( !etm->frozen ) + e_table_model_changed(etm); +} + +gboolean +e_table_subset_variable_remove (ETableSubsetVariable *etssv, + gint row) +{ + ETableModel *etm = E_TABLE_MODEL(etssv); + ETableSubset *etss = E_TABLE_SUBSET(etssv); + int i; + + for ( i = 0; i < etss->n_map; i++ ) { + if (etss->map_table[i] == row) { + memmove(etss->map_table + i, etss->map_table + i + 1, (etss->n_map - i - 1) * sizeof(int)); + etss->n_map --; + if ( !etm->frozen ) + e_table_model_changed(etm); + return TRUE; + } + } + return FALSE; +} + +void +e_table_subset_variable_increment (ETableSubsetVariable *etssv, + gint position, + gint amount) +{ + int i; + ETableSubset *etss = E_TABLE_SUBSET(etssv); + for ( i = 0; i < etss->n_map; i++ ) { + if ( etss->map_table[i] > position ) + etss->map_table[i] += amount; + } +} + +void +e_table_subset_variable_set_allocation (ETableSubsetVariable *etssv, + gint total) +{ + ETableSubset *etss = E_TABLE_SUBSET(etssv); + if ( total <= 0 ) + total = 1; + if ( total > etss->n_map ) { + etss->map_table = g_realloc(etss->map_table, total * sizeof(int)); + } +} diff --git a/widgets/e-table/e-table-subset-variable.h b/widgets/e-table/e-table-subset-variable.h new file mode 100644 index 0000000000..9755fb2477 --- /dev/null +++ b/widgets/e-table/e-table-subset-variable.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#ifndef _E_TABLE_SUBSET_VARIABLE_H_ +#define _E_TABLE_SUBSET_VARIABLE_H_ + +#include <gtk/gtkobject.h> +#include "e-table-subset.h" + +#define E_TABLE_SUBSET_VARIABLE_TYPE (e_table_subset_variable_get_type ()) +#define E_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariable)) +#define E_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SUBSET_VARIABLE_TYPE, ETableSubsetVariableClass)) +#define E_IS_TABLE_SUBSET_VARIABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_SUBSET_VARIABLE_TYPE)) +#define E_IS_TABLE_SUBSET_VARIABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SUBSET_VARIABLE_TYPE)) + +typedef struct { + ETableSubset base; + + int n_vals_allocated; +} ETableSubsetVariable; + +typedef struct { + ETableSubsetClass parent_class; +} ETableSubsetVariableClass; + +GtkType e_table_subset_variable_get_type (void); +ETableModel *e_table_subset_variable_new (ETableModel *etm); +ETableModel *e_table_subset_variable_construct (ETableSubsetVariable *etssv, + ETableModel *source); +void e_table_subset_variable_add (ETableSubsetVariable *ets, + gint row); +gboolean e_table_subset_variable_remove (ETableSubsetVariable *ets, + gint row); +void e_table_subset_variable_increment (ETableSubsetVariable *ets, + gint position, + gint amount); +void e_table_subset_variable_set_allocation (ETableSubsetVariable *ets, + gint total); +#endif /* _E_TABLE_SUBSET_VARIABLE_H_ */ + diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c index a9e4a5c5a4..a09d221980 100644 --- a/widgets/e-table/e-table-subset.c +++ b/widgets/e-table/e-table-subset.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * E-table-subset.c: Implements a table that contains a subset of another table. * @@ -71,6 +72,12 @@ etss_is_cell_editable (ETableModel *etm, int col, int row) } static void +etss_thaw (ETableModel *etm) +{ + e_table_model_changed (etm); +} + +static void etss_class_init (GtkObjectClass *klass) { ETableModelClass *table_class = (ETableModelClass *) klass; @@ -84,6 +91,7 @@ etss_class_init (GtkObjectClass *klass) table_class->value_at = etss_value_at; table_class->set_value_at = etss_set_value_at; table_class->is_cell_editable = etss_is_cell_editable; + table_class->thaw = etss_thaw; } E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE); @@ -91,20 +99,23 @@ E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, static void etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss) { - e_table_model_changed (E_TABLE_MODEL (etss)); + if ( !E_TABLE_MODEL(etss)->frozen ) + e_table_model_changed (E_TABLE_MODEL (etss)); } static void etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_row_changed (E_TABLE_MODEL (etss), i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_row_changed (E_TABLE_MODEL (etss), i); + return; + } } } } @@ -112,14 +123,16 @@ etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss) static void etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss) { - const int n = etss->n_map; - const int * const map_table = etss->map_table; - int i; - - for (i = 0; i < n; i++){ - if (map_table [i] == row){ - e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); - return; + if ( !E_TABLE_MODEL(etss)->frozen ) { + const int n = etss->n_map; + const int * const map_table = etss->map_table; + int i; + + for (i = 0; i < n; i++){ + if (map_table [i] == row){ + e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i); + return; + } } } } @@ -130,7 +143,7 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals) unsigned int *buffer; int i; - buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals); + buffer = (unsigned int *) g_malloc (sizeof (unsigned int) * nvals); if (buffer == NULL) return NULL; etss->map_table = buffer; diff --git a/widgets/e-table/e-table-subset.h b/widgets/e-table/e-table-subset.h index 314f28aea6..d8af1696f5 100644 --- a/widgets/e-table/e-table-subset.h +++ b/widgets/e-table/e-table-subset.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_SUBSET_H_ #define _E_TABLE_SUBSET_H_ diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index 46531113e4..551ef52227 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -1,5 +1,6 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * E-table-view.c: A graphical view of a Table. + * E-table.c: A graphical view of a Table. * * Author: * Miguel de Icaza (miguel@gnu.org) @@ -16,7 +17,9 @@ #include <stdio.h> #include <libgnomeui/gnome-canvas.h> #include <gtk/gtksignal.h> +#include <gnome-xml/parser.h> #include "e-util/e-util.h" +#include "e-util/e-xml-utils.h" #include "e-table.h" #include "e-table-header-item.h" #include "e-table-subset.h" @@ -40,8 +43,6 @@ et_destroy (GtkObject *object) gtk_object_unref (GTK_OBJECT (et->full_header)); gtk_object_unref (GTK_OBJECT (et->header)); - g_free (et->group_spec); - (*e_table_parent_class->destroy)(object); } @@ -56,19 +57,16 @@ e_table_init (GtkObject *object) } static ETableHeader * -e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols) +e_table_make_header (ETable *e_table, ETableHeader *full_header, xmlNode *xmlColumns) { ETableHeader *nh; - char *copy = alloca (strlen (cols) + 1); - char *p, *state; + xmlNode *column; const int max_cols = e_table_header_count (full_header); nh = e_table_header_new (); - strcpy (copy, cols); - while ((p = strtok_r (copy, ",", &state)) != NULL){ - int col = atoi (p); + for (column = xmlColumns->childs; column; column = column->next) { + int col = atoi (column->childs->content); - copy = NULL; if (col >= max_cols) continue; @@ -113,6 +111,7 @@ e_table_setup_header (ETable *e_table) } +#if 0 typedef struct { void *value; GArray *array; @@ -201,7 +200,7 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } - +#endif typedef struct _Node Node; struct _Node { @@ -212,7 +211,7 @@ struct _Node { guint is_leaf:1; }; - +#if 0 static Node * leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) { @@ -335,8 +334,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - - group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "columns", ecol, TRUE, parent == NULL); group = node_new (group_item, model, parent); for (i = 0; tables [i] != NULL; i++){ @@ -347,8 +347,9 @@ e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, GnomeCanvasItem *item_leaf_header; Node *leaf_header; + /* FIXME *//* item_leaf_header = e_table_group_new ( - GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE); + GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE);*/ leaf_header = node_new (item_leaf_header, tables [i], group); e_table_create_leaf (e_table, tables [i], leaf_header); @@ -424,6 +425,14 @@ static GnomeCanvasClass *e_table_canvas_parent_class; static void e_table_canvas_realize (GtkWidget *widget) { +#if 0 + GnomeCanvasItem *group_item; + + group_item = gnome_canvas_item_new (root, + e_table_group_get_type(), + "header", E_TABLE, TRUE, parent == NULL); + + ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; int *groups; @@ -433,6 +442,8 @@ e_table_canvas_realize (GtkWidget *widget) groups = group_spec_to_desc (e_table->group_spec); + + leaf = e_table_create_nodes ( e_table, e_table->model, e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, groups); @@ -440,6 +451,7 @@ e_table_canvas_realize (GtkWidget *widget) if (groups) g_free (groups); +#endif } static void @@ -496,33 +508,75 @@ e_table_canvas_new (ETable *e_table) return GNOME_CANVAS (e_table_canvas); } +#endif static void -table_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) +table_canvas_size_allocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table) { + gdouble height; + gdouble width; + gtk_object_get(GTK_OBJECT(e_table->group), + "height", &height, + NULL); gnome_canvas_set_scroll_region ( GNOME_CANVAS (e_table->table_canvas), - 0, 0, alloc->width, alloc->height); + 0, 0, alloc->width, MAX(height, alloc->height)); + width = alloc->width; + gtk_object_set(GTK_OBJECT(e_table->group), + "width", width, + NULL); } static void -e_table_setup_table (ETable *e_table) +e_table_setup_table (ETable *e_table, ETableHeader *full_header, ETableHeader *header, ETableModel *model, xmlNode *xml_grouping) { - e_table->table_canvas = e_table_canvas_new (e_table); + e_table->table_canvas = GNOME_CANVAS(gnome_canvas_new ()); gtk_signal_connect ( GTK_OBJECT (e_table->table_canvas), "size_allocate", - GTK_SIGNAL_FUNC (table_canvas_size_alocate), e_table); + GTK_SIGNAL_FUNC (table_canvas_size_allocate), e_table); gtk_widget_show (GTK_WIDGET (e_table->table_canvas)); gtk_table_attach ( GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas), 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); + + e_table->group = e_table_group_new(GNOME_CANVAS_GROUP(e_table->table_canvas->root), + full_header, + header, + model, + xml_grouping->childs); + +} + +static void +e_table_fill_table (ETable *e_table, ETableModel *model) +{ + int count; + int i; + count = e_table_model_row_count(model); + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", TRUE, + NULL); + for ( i = 0; i < count; i++ ) { + e_table_group_add(e_table->group, i); + } + gtk_object_set(GTK_OBJECT(e_table->group), + "frozen", FALSE, + NULL); } void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec) + const char *spec) { + xmlDoc *xmlSpec; + xmlNode *xmlRoot; + xmlNode *xmlColumns; + xmlNode *xmlGrouping; + + char *copy; + copy = g_strdup(spec); + GTK_TABLE (e_table)->homogeneous = FALSE; gtk_table_resize (GTK_TABLE (e_table), 1, 2); @@ -532,24 +586,29 @@ e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, e_table->model = etm; gtk_object_ref (GTK_OBJECT (etm)); + + xmlSpec = xmlParseMemory(copy, strlen(copy) + 1); + e_table->specification = xmlSpec; - e_table->header = e_table_make_header (e_table, full_header, cols_spec); + xmlRoot = xmlDocGetRootElement(xmlSpec); + xmlColumns = e_xml_get_child_by_name(xmlRoot, "columns-shown"); + xmlGrouping = e_xml_get_child_by_name(xmlRoot, "grouping"); + + e_table->header = e_table_make_header (e_table, full_header, xmlColumns); e_table_setup_header (e_table); - e_table_setup_table (e_table); - - e_table->group_spec = g_strdup (group_spec); - + e_table_setup_table (e_table, full_header, e_table->header, etm, xmlGrouping); + e_table_fill_table (e_table, etm); } GtkWidget * -e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec) +e_table_new (ETableHeader *full_header, ETableModel *etm, const char *spec) { ETable *e_table; e_table = gtk_type_new (e_table_get_type ()); - e_table_construct (e_table, full_header, etm, cols_spec, group_spec); + e_table_construct (e_table, full_header, etm, spec); return (GtkWidget *) e_table; } diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index 63c131324f..a372d8042c 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -1,10 +1,13 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #ifndef _E_TABLE_H_ #define _E_TABLE_H_ #include <libgnomeui/gnome-canvas.h> #include <gtk/gtktable.h> +#include <gnome-xml/tree.h> #include "e-table-model.h" #include "e-table-header.h" +#include "e-table-group.h" BEGIN_GNOME_DECLS @@ -21,15 +24,17 @@ typedef struct { ETableHeader *full_header, *header; + ETableGroup *group; + GnomeCanvas *header_canvas, *table_canvas; GnomeCanvasItem *header_item, *root; + + xmlDoc *specification; guint draw_grid:1; guint draw_focus:1; guint spreadsheet:1; - - char *group_spec; } ETable; typedef struct { @@ -38,9 +43,9 @@ typedef struct { GtkType e_table_get_type (void); void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, - const char *cols_spec, const char *group_spec); + const char *spec); END_GNOME_DECLS diff --git a/widgets/e-table/test-check.c b/widgets/e-table/test-check.c index 380da8048e..a6a59788ad 100644 --- a/widgets/e-table/test-check.c +++ b/widgets/e-table/test-check.c @@ -13,6 +13,7 @@ #include "e-table-header-item.h" #include "e-table-item.h" #include "e-util/e-cursors.h" +#include "e-util/e-canvas-utils.h" #include "e-cell-text.h" #include "e-cell-checkbox.h" @@ -79,6 +80,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -93,13 +100,14 @@ check_test (void) ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_check; GdkPixbuf *pixbuf; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -137,21 +145,15 @@ check_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 0, 30); } - - - - diff --git a/widgets/e-table/test-cols.c b/widgets/e-table/test-cols.c index 3fe17ae555..adc9ed6c20 100644 --- a/widgets/e-table/test-cols.c +++ b/widgets/e-table/test-cols.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <string.h> #include <gnome.h> +#include "e-util/e-canvas-utils.h" #include "e-util/e-cursors.h" #include "e-table-simple.h" #include "e-table-header.h" @@ -84,6 +85,12 @@ set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); } +static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + void multi_cols_test (void) { @@ -92,13 +99,14 @@ multi_cols_test (void) ETableHeader *e_table_header, *e_table_header_multiple; ETableCol *col_0, *col_1; ECell *cell_left_just, *cell_image_toggle; + GnomeCanvasItem *item; gtk_widget_push_visual (gdk_rgb_get_visual ()); gtk_widget_push_colormap (gdk_rgb_get_cmap ()); e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -157,17 +165,17 @@ multi_cols_test (void) "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); + + e_canvas_item_move_absolute(item, 0, 30); gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), @@ -176,18 +184,16 @@ multi_cols_test (void) "x", 300, "y", 0, NULL); - gnome_canvas_item_new ( + item = gnome_canvas_item_new ( gnome_canvas_root (GNOME_CANVAS (canvas)), e_table_item_get_type (), "ETableHeader", e_table_header_multiple, "ETableModel", e_table_model, - "x", (double) 300, - "y", (double) 30, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, NULL); - + e_canvas_item_move_absolute(item, 300, 30); } diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c index 27e1ac59f1..1bd50e1479 100644 --- a/widgets/e-table/test-table.c +++ b/widgets/e-table/test-table.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Test code for the ETable package * @@ -55,6 +56,8 @@ parse_headers () p = buffer; for (i = 0; (s = strtok (p, " \t")) != NULL; i++){ column_labels [i] = g_strdup (s); + if ( strchr(column_labels [i], '\n') ) + *strchr(column_labels [i], '\n') = 0; p = NULL; } @@ -174,6 +177,12 @@ is_cell_editable (ETableModel *etc, int col, int row, void *data) } static void +thaw (ETableModel *etc, void *data) +{ + e_table_model_changed(etc); +} + +static void set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc) { gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height); @@ -196,7 +205,7 @@ table_browser_test (void) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); /* * Header @@ -244,8 +253,6 @@ table_browser_test (void) e_table_item_get_type (), "ETableHeader", e_table_header, "ETableModel", e_table_model, - "x", (double) 0, - "y", (double) 0, "drawgrid", TRUE, "drawfocus", TRUE, "spreadsheet", TRUE, @@ -253,7 +260,7 @@ table_browser_test (void) } static void -do_e_table_demo (const char *col_spec, const char *group_spec) +do_e_table_demo (const char *spec) { GtkWidget *e_table, *window, *frame; ETableModel *e_table_model; @@ -266,7 +273,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) */ e_table_model = e_table_simple_new ( col_count, row_count, value_at, - set_value_at, is_cell_editable, NULL); + set_value_at, is_cell_editable, thaw, NULL); full_header = e_table_header_new (); cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT, TRUE); @@ -283,7 +290,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) window = gtk_window_new (GTK_WINDOW_TOPLEVEL); frame = gtk_frame_new (NULL); - e_table = e_table_new (full_header, e_table_model, col_spec, group_spec); + e_table = e_table_new (full_header, e_table_model, spec); gtk_container_add (GTK_CONTAINER (frame), e_table); gtk_container_add (GTK_CONTAINER (window), frame); @@ -298,9 +305,10 @@ e_table_test (void) { load_data (); - if (getenv ("DO")){ - do_e_table_demo ("0,1,2,3,4", NULL); - do_e_table_demo ("0,1,2,3,4", "3,4"); + if (1){/*getenv ("DO")){*/ + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <leaf/> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <group column=\"4\"> <leaf/> </group> </group> </grouping> </ETableSpecification>"); } - do_e_table_demo ("0,1,2,3,4", "3"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"4\"> <leaf/> </group> </grouping> </ETableSpecification>"); + do_e_table_demo ("<ETableSpecification> <columns-shown> <column> 0 </column> <column> 1 </column> <column> 2 </column> <column> 3 </column> <column> 4 </column> </columns-shown> <grouping> <group column=\"3\"> <leaf/> </group> </grouping> </ETableSpecification>"); } |