diff options
Diffstat (limited to 'widgets')
32 files changed, 1486 insertions, 549 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog index 7e75163aae..f3eeb358b3 100644 --- a/widgets/ChangeLog +++ b/widgets/ChangeLog @@ -1,3 +1,17 @@ +1999-12-22 Miguel de Icaza <miguel@helixcode.com> + + * e-table-item.c (e_table_item_focus): grab focus here with the + canvas method. + +1999-12-20 Miguel de Icaza <miguel@helixcode.com> + + * e-table-group.c (etg_update): Change the dimensions only if the + child changes its own. + + * e-table-item.c (eti_table_model_changed): Emit new signal on + table height change. + (eti_class_init): Register new "height_change" signal. + 1999-12-19 Damon Chaplin <damon@karuna.freeserve.co.uk> * Makefile.am (SUBDIRS): created SUBDIRS with meeting-time-sel. diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c index 79fe432326..9d599f3d4c 100644 --- a/widgets/e-cell-text.c +++ b/widgets/e-cell-text.c @@ -221,7 +221,10 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, */ if ((px + left_len) > x2) px -= left_len - (x2-x1); - + + /* + * Draw + */ for (i = 0, p = text_wc; *p; p++, i++){ gdk_draw_text_wc ( drawable, font, gc, px, y, p, 1); diff --git a/widgets/e-table-group.c b/widgets/e-table-group.c index 76c317369e..8765c3b83c 100644 --- a/widgets/e-table-group.c +++ b/widgets/e-table-group.c @@ -10,6 +10,7 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> #include "e-util.h" @@ -20,71 +21,67 @@ static GnomeCanvasGroupClass *etg_parent_class; +enum { + HEIGHT_CHANGED, + LAST_SIGNAL +}; + +static gint etg_signals [LAST_SIGNAL] = { 0, }; + static void etg_destroy (GtkObject *object) { ETableGroup *etg = E_TABLE_GROUP (object); - gtk_object_unref (GTK_OBJECT (etg->ecol)); - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); } -static int -etg_width (ETableGroup *etg) +static void +etg_dim (ETableGroup *etg, int *width, int *height) { - return e_table_header_total_width (etg->header) + GROUP_INDENT; -} + GSList *l; -static int -etg_height (ETableGroup *etg) -{ - GnomeCanvasItem *child = etg->child; + *width = *height = 0; - return TITLE_HEIGHT + (child->y2 - child->y1); -} + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; -static void -etg_header_changed (ETableHeader *header, ETableGroup *etg) -{ - gnome_canvas_item_set ( - etg->rect, - "x2", (double) etg_width (etg), - NULL); + *height += child->y2 - child->y1; + *width += child->x2 - child->x1; + } + + if (!etg->transparent){ + *height += TITLE_HEIGHT; + *width += GROUP_INDENT; + } } void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open) + ETableCol *ecol, gboolean open, + gboolean transparent) { gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - gtk_object_ref (GTK_OBJECT (header)); - - etg->header = header; - etg->col = col; - etg->ecol = e_table_header_get_column (header, col); + etg->ecol = ecol; etg->open = open; + etg->transparent = transparent; + + etg_dim (etg, &etg->width, &etg->height); - gtk_signal_connect ( - GTK_OBJECT (header), "dimension_change", - GTK_SIGNAL_FUNC (etg_header_changed), etg); - - etg->child = child; - - 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 (etg), - "y2", (double) etg_height (etg), - NULL); + 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); - +#if 0 /* * Reparent the child into our space. */ @@ -95,30 +92,151 @@ e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, "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, ETableHeader *header, int col, GnomeCanvasItem *child, int open) +e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent) { ETableGroup *etg; g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (header != NULL, NULL); - g_return_val_if_fail (child != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); etg = gtk_type_new (e_table_group_get_type ()); - e_table_group_construct (parent, etg, header, col, child, open); + e_table_group_construct (parent, etg, ecol, open, transparent); return GNOME_CANVAS_ITEM (etg); } static void +etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +{ + GSList *l; + int height = etg->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etg->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 != etg->height){ + etg->height = height; + gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); + } +} + +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_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 ("Positioning item %p at %d\n", item, height); + 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); + } + } +} + +static void etg_realize (GnomeCanvasItem *item) { ETableGroup *etg = E_TABLE_GROUP (item); + GSList *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); + } + } } static void @@ -129,8 +247,20 @@ etg_class_init (GtkObjectClass *object_class) object_class->destroy = etg_destroy; item_class->realize = etg_realize; - + item_class->update = etg_update; + etg_parent_class = gtk_type_class (PARENT_TYPE); + + etg_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + 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-group.h b/widgets/e-table-group.h index 18f4b710b1..468d5dd794 100644 --- a/widgets/e-table-group.h +++ b/widgets/e-table-group.h @@ -14,22 +14,50 @@ typedef struct { GnomeCanvasGroup group; - ETableHeader *header; + /* + * The ETableCol used to group this set + */ ETableCol *ecol; - int col; - int open; - GnomeCanvasItem *rect, *child; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + /* + * Dimensions of the ETableGroup + */ + int width, height; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; + + /* + * Whether we should add indentation and open/close markers, + * or if we just act as containers of subtables. + */ + guint transparent:1; + + /* + * List of GnomeCanvasItems we stack + */ + GSList *children; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; + void (*height_changed) (ETableGroup *etg); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *header, - int col, GnomeCanvasItem *child, int open); +GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent); void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open); -GtkType e_table_group_get_type (void); + ETableCol *ecol, gboolean open, gboolean transparent); + +void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); + +GtkType e_table_group_get_type (void); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c index 23b72d5557..f9c5bc197d 100644 --- a/widgets/e-table-item.c +++ b/widgets/e-table-item.c @@ -26,6 +26,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, + HEIGHT_CHANGED, LAST_SIGNAL }; @@ -97,18 +98,12 @@ eti_unrealize_cell_views (ETableItem *eti) } -/* - * GnomeCanvasItem::update method - */ static void -eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +eti_bounds (ETableItem *eti, double *x1, double *y1, double *x2, double *y2) { - ETableItem *eti = E_TABLE_ITEM (item); double i2c [6]; ArtPoint c1, c2, i1, i2; - - if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) - (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (eti); gnome_canvas_item_i2c_affine (item, i2c); i1.x = eti->x1; @@ -122,9 +117,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) item->y1 = c1.y; item->x2 = c2.x; item->y2 = c2.y; +} - printf ("BBOX: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); + +/* + * GnomeCanvasItem::update method + */ +static void +eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableItem *eti = E_TABLE_ITEM (item); + if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + + eti_bounds (eti, &item->x1, &item->y1, &item->x2, &item->y2); gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); } @@ -238,6 +245,22 @@ eti_get_height (ETableItem *eti) return height; } +static void +eti_compute_height (ETableItem *eti) +{ + int new_height = eti_get_height (eti); + + if (new_height != eti->height){ + 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]); + } +} + /* * Callback routine: invoked when the ETableModel has suffered a change */ @@ -247,7 +270,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) - eti->height = eti_get_height (eti); + eti_compute_height (eti); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } @@ -368,6 +391,7 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); + eti->table_model_row_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_row_changed", GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); @@ -547,7 +571,8 @@ eti_realize (GnomeCanvasItem *item) */ eti_realize_cell_views (eti); - eti->height = eti_get_height (eti); + eti_compute_height (eti); + eti_update (item, NULL, NULL, 0); } @@ -799,6 +824,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub return TRUE; } +static void +eti_cursor_move_left (ETableItem *eti) +{ + e_table_item_leave_edit (eti); + e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); +} + +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); +} + +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); +} + +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); +} + static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { @@ -874,35 +927,53 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if (eti->focused_col > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); - } + if (eti->focused_col > 0) + eti_cursor_move_left (eti); + return TRUE; case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); - } + if ((eti->focused_col + 1) < eti->cols) + eti_cursor_move_right (eti); return TRUE; case GDK_Up: - if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); - } + if (eti->focused_row > 0) + eti_cursor_move_up (eti); return TRUE; case GDK_Down: - if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); - } + if ((eti->focused_row + 1) < eti->rows) + eti_cursor_move_down (eti); + return TRUE; + + case GDK_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_col + 1) < eti->cols) + 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 */ + } + } + break; + default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) @@ -967,7 +1038,8 @@ eti_class_init (GtkObjectClass *object_class) item_class->draw = eti_draw; item_class->point = eti_point; item_class->event = eti_event; - + item_class->bounds = eti_bounds; + eti_class->row_selection = eti_row_selection; gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER, @@ -992,6 +1064,14 @@ eti_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableItemClass, row_selection), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); + + eti_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL); @@ -1037,7 +1117,7 @@ e_table_item_focus (ETableItem *eti, int col, int row) /* * make sure we have the Gtk Focus */ - gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas)); + gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (eti)); } void diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h index e9125431b1..0867a09d6b 100644 --- a/widgets/e-table-item.h +++ b/widgets/e-table-item.h @@ -67,6 +67,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); + void (*height_changed) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); diff --git a/widgets/e-table-model.h b/widgets/e-table-model.h index fb37731a8a..2d08f3744e 100644 --- a/widgets/e-table-model.h +++ b/widgets/e-table-model.h @@ -56,5 +56,3 @@ void e_table_model_row_changed (ETableModel *e_table_model, int row) void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row); #endif /* _E_TABLE_MODEL_H_ */ - - diff --git a/widgets/e-table.c b/widgets/e-table.c index b5f77f622b..ff81866361 100644 --- a/widgets/e-table.c +++ b/widgets/e-table.c @@ -29,17 +29,6 @@ static GtkObjectClass *e_table_parent_class; -typedef struct { - ETableModel *table; - GnomeCanvasItem *table_item; - GnomeCanvasItem *lead; -} Leaf; - -typedef struct { - -} Node; - - static void et_destroy (GtkObject *object) { @@ -122,38 +111,6 @@ e_table_setup_header (ETable *e_table) } -static Leaf * -e_table_create_leaf (ETable *e_table, ETableModel *etm, int col, int height) -{ - Leaf *leaf; - - leaf = g_new (Leaf, 1); - leaf->table = etm; - - leaf->table_item = gnome_canvas_item_new ( - gnome_canvas_root (e_table->table_canvas), - e_table_item_get_type (), - "ETableHeader", e_table->header, - "ETableModel", etm, - "x", (double) 0, - "y", (double) 0, - "drawgrid", e_table->draw_grid, - "drawfocus", e_table->draw_focus, - "spreadsheet", e_table->spreadsheet, - NULL); - - leaf->lead = e_table_group_new ( - gnome_canvas_root (e_table->table_canvas), - e_table->header, col, leaf->table_item, TRUE); - - gnome_canvas_item_set ( - leaf->lead, - "y", (double) height, - NULL); - - return leaf; -} - typedef struct { void *value; GArray *array; @@ -232,7 +189,6 @@ e_table_make_subtables (ETableModel *model, GArray *groups) ETableSubset *ss; int j; - printf ("Creating subset of %d elements\n", sub_size); tables [i] = e_table_subset_new (model, sub_size); ss = E_TABLE_SUBSET (tables [i]); @@ -244,68 +200,167 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } +typedef struct _Node Node; + +struct _Node { + Node *parent; + GnomeCanvasItem *item; + ETableModel *table_model; + GSList *children; + + guint is_leaf:1; +}; + +static Node * +leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_item != NULL); + g_assert (table_model != NULL); + g_assert (parent != NULL); + + node->item = table_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 1; + + g_assert (!parent->is_leaf); + + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), table_item); + + return node; +} + +static Node * +node_new (GnomeCanvasItem *group_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_model != NULL); + + node->children = NULL; + node->item = group_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 0; + + if (parent){ + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), group_item); + } + + return node; +} + +static Node * +e_table_create_leaf (ETable *e_table, ETableModel *etm, Node *parent) +{ + GnomeCanvasItem *table_item; + static double last_y; + Node *leaf; + + table_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (parent->item), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + leaf = leaf_new (table_item, etm, parent); + + return leaf; +} + static int -leaf_height (Leaf *leaf) +leaf_height (Node *leaf) { - return leaf->lead->y2 - leaf->lead->y1; + const GnomeCanvasItem *item = leaf->item; + + return item->y2 - item->y1; } -static Leaf * +static int +leaf_event (GnomeCanvasItem *item, GdkEvent *event) +{ + static int last_x = -1; + static int last_y = -1; + + if (event->type == GDK_BUTTON_PRESS){ + last_x = event->button.x; + last_y = event->button.y; + } else if (event->type == GDK_BUTTON_RELEASE){ + last_x = -1; + last_y = -1; + } else if (event->type == GDK_MOTION_NOTIFY){ + if (last_x == -1) + return FALSE; + + gnome_canvas_item_move (item, event->motion.x - last_x, event->motion.y - last_y); + last_x = event->motion.x; + last_y = event->motion.y; + } else + return FALSE; + return TRUE; +} + +static Node * e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, - GnomeCanvasGroup *root, int height, int *groups_list) + GnomeCanvasGroup *root, Node *parent, int *groups_list) { GArray *groups; ETableModel **tables; + ETableCol *ecol; int key_col, i; - GCompareFunc comp; - Leaf *leaf; - GnomeCanvasItem *group; - - if (groups_list) - key_col = *groups_list; - else - key_col = -1; - - if (key_col == -1){ - printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); - leaf = e_table_create_leaf (e_table, model, key_col, height); - - return leaf; - } + GnomeCanvasItem *group_item; + Node *group; + key_col = *groups_list; + g_assert (key_col != -1); + /* * Create groups */ - comp = e_table_header_get_column (header, key_col)->compare; - groups = e_table_create_groups (model, key_col, comp); + ecol = e_table_header_get_column (header, key_col); + + g_assert (ecol != NULL); + + groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - leaf = g_new0 (Leaf, 1); - - leaf->table = NULL; - leaf->table_item = NULL; - group = gnome_canvas_item_new ( - root, - gnome_canvas_group_get_type (), - NULL); - - height = 0; + group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group = node_new (group_item, model, parent); + for (i = 0; tables [i] != NULL; i++){ - printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); - - leaf = e_table_create_nodes ( - e_table, tables [i], header, GNOME_CANVAS_GROUP (group), height, - &groups_list [1]); + Node *node; - height += leaf_height (leaf); + /* + * Leafs + */ + if (groups_list [1] == -1){ + GnomeCanvasItem *item_leaf_header; + Node *leaf_header; + + item_leaf_header = e_table_group_new ( + 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); + } else { + e_table_create_nodes ( + e_table, tables [i], header, GNOME_CANVAS_GROUP (group_item), + group, &groups_list [1]); + } } - leaf->lead = e_table_group_new ( - root, - e_table->header, key_col, group, TRUE); - - return leaf; + return group; } static int * @@ -372,9 +427,9 @@ e_table_canvas_realize (GtkWidget *widget) { ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; - Leaf *leaf; int *groups; - + Node *leaf; + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); groups = group_spec_to_desc (e_table->group_spec); @@ -434,10 +489,16 @@ e_table_canvas_class_init (GtkObjectClass *object_class) e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); } +static void +e_table_canvas_init (GtkObject *canvas) +{ + GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS); +} + GtkType e_table_canvas_get_type (void); E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, - NULL, E_TABLE_CANVAS_PARENT_TYPE); + e_table_canvas_init, E_TABLE_CANVAS_PARENT_TYPE); static GnomeCanvas * e_table_canvas_new (ETable *e_table) diff --git a/widgets/e-table.h b/widgets/e-table.h index eb089781b9..e2a5a3e9d5 100644 --- a/widgets/e-table.h +++ b/widgets/e-table.h @@ -50,4 +50,4 @@ GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, END_GNOME_DECLS -#endif /* _E_TABLE_H_ */ + #endif /* _E_TABLE_H_ */ diff --git a/widgets/e-table/ChangeLog b/widgets/e-table/ChangeLog index 7e75163aae..f3eeb358b3 100644 --- a/widgets/e-table/ChangeLog +++ b/widgets/e-table/ChangeLog @@ -1,3 +1,17 @@ +1999-12-22 Miguel de Icaza <miguel@helixcode.com> + + * e-table-item.c (e_table_item_focus): grab focus here with the + canvas method. + +1999-12-20 Miguel de Icaza <miguel@helixcode.com> + + * e-table-group.c (etg_update): Change the dimensions only if the + child changes its own. + + * e-table-item.c (eti_table_model_changed): Emit new signal on + table height change. + (eti_class_init): Register new "height_change" signal. + 1999-12-19 Damon Chaplin <damon@karuna.freeserve.co.uk> * Makefile.am (SUBDIRS): created SUBDIRS with meeting-time-sel. diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c index 79fe432326..9d599f3d4c 100644 --- a/widgets/e-table/e-cell-text.c +++ b/widgets/e-table/e-cell-text.c @@ -221,7 +221,10 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, */ if ((px + left_len) > x2) px -= left_len - (x2-x1); - + + /* + * Draw + */ for (i = 0, p = text_wc; *p; p++, i++){ gdk_draw_text_wc ( drawable, font, gc, px, y, p, 1); diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c index 76c317369e..8765c3b83c 100644 --- a/widgets/e-table/e-table-group.c +++ b/widgets/e-table/e-table-group.c @@ -10,6 +10,7 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> #include "e-util.h" @@ -20,71 +21,67 @@ static GnomeCanvasGroupClass *etg_parent_class; +enum { + HEIGHT_CHANGED, + LAST_SIGNAL +}; + +static gint etg_signals [LAST_SIGNAL] = { 0, }; + static void etg_destroy (GtkObject *object) { ETableGroup *etg = E_TABLE_GROUP (object); - gtk_object_unref (GTK_OBJECT (etg->ecol)); - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); } -static int -etg_width (ETableGroup *etg) +static void +etg_dim (ETableGroup *etg, int *width, int *height) { - return e_table_header_total_width (etg->header) + GROUP_INDENT; -} + GSList *l; -static int -etg_height (ETableGroup *etg) -{ - GnomeCanvasItem *child = etg->child; + *width = *height = 0; - return TITLE_HEIGHT + (child->y2 - child->y1); -} + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; -static void -etg_header_changed (ETableHeader *header, ETableGroup *etg) -{ - gnome_canvas_item_set ( - etg->rect, - "x2", (double) etg_width (etg), - NULL); + *height += child->y2 - child->y1; + *width += child->x2 - child->x1; + } + + if (!etg->transparent){ + *height += TITLE_HEIGHT; + *width += GROUP_INDENT; + } } void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open) + ETableCol *ecol, gboolean open, + gboolean transparent) { gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - gtk_object_ref (GTK_OBJECT (header)); - - etg->header = header; - etg->col = col; - etg->ecol = e_table_header_get_column (header, col); + etg->ecol = ecol; etg->open = open; + etg->transparent = transparent; + + etg_dim (etg, &etg->width, &etg->height); - gtk_signal_connect ( - GTK_OBJECT (header), "dimension_change", - GTK_SIGNAL_FUNC (etg_header_changed), etg); - - etg->child = child; - - 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 (etg), - "y2", (double) etg_height (etg), - NULL); + 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); - +#if 0 /* * Reparent the child into our space. */ @@ -95,30 +92,151 @@ e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, "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, ETableHeader *header, int col, GnomeCanvasItem *child, int open) +e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent) { ETableGroup *etg; g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (header != NULL, NULL); - g_return_val_if_fail (child != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); etg = gtk_type_new (e_table_group_get_type ()); - e_table_group_construct (parent, etg, header, col, child, open); + e_table_group_construct (parent, etg, ecol, open, transparent); return GNOME_CANVAS_ITEM (etg); } static void +etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +{ + GSList *l; + int height = etg->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etg->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 != etg->height){ + etg->height = height; + gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); + } +} + +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_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 ("Positioning item %p at %d\n", item, height); + 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); + } + } +} + +static void etg_realize (GnomeCanvasItem *item) { ETableGroup *etg = E_TABLE_GROUP (item); + GSList *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); + } + } } static void @@ -129,8 +247,20 @@ etg_class_init (GtkObjectClass *object_class) object_class->destroy = etg_destroy; item_class->realize = etg_realize; - + item_class->update = etg_update; + etg_parent_class = gtk_type_class (PARENT_TYPE); + + etg_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + 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 18f4b710b1..468d5dd794 100644 --- a/widgets/e-table/e-table-group.h +++ b/widgets/e-table/e-table-group.h @@ -14,22 +14,50 @@ typedef struct { GnomeCanvasGroup group; - ETableHeader *header; + /* + * The ETableCol used to group this set + */ ETableCol *ecol; - int col; - int open; - GnomeCanvasItem *rect, *child; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + /* + * Dimensions of the ETableGroup + */ + int width, height; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; + + /* + * Whether we should add indentation and open/close markers, + * or if we just act as containers of subtables. + */ + guint transparent:1; + + /* + * List of GnomeCanvasItems we stack + */ + GSList *children; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; + void (*height_changed) (ETableGroup *etg); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *header, - int col, GnomeCanvasItem *child, int open); +GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent); void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open); -GtkType e_table_group_get_type (void); + ETableCol *ecol, gboolean open, gboolean transparent); + +void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); + +GtkType e_table_group_get_type (void); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/e-table/e-table-item.c b/widgets/e-table/e-table-item.c index 23b72d5557..f9c5bc197d 100644 --- a/widgets/e-table/e-table-item.c +++ b/widgets/e-table/e-table-item.c @@ -26,6 +26,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, + HEIGHT_CHANGED, LAST_SIGNAL }; @@ -97,18 +98,12 @@ eti_unrealize_cell_views (ETableItem *eti) } -/* - * GnomeCanvasItem::update method - */ static void -eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +eti_bounds (ETableItem *eti, double *x1, double *y1, double *x2, double *y2) { - ETableItem *eti = E_TABLE_ITEM (item); double i2c [6]; ArtPoint c1, c2, i1, i2; - - if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) - (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (eti); gnome_canvas_item_i2c_affine (item, i2c); i1.x = eti->x1; @@ -122,9 +117,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) item->y1 = c1.y; item->x2 = c2.x; item->y2 = c2.y; +} - printf ("BBOX: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); + +/* + * GnomeCanvasItem::update method + */ +static void +eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableItem *eti = E_TABLE_ITEM (item); + if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + + eti_bounds (eti, &item->x1, &item->y1, &item->x2, &item->y2); gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); } @@ -238,6 +245,22 @@ eti_get_height (ETableItem *eti) return height; } +static void +eti_compute_height (ETableItem *eti) +{ + int new_height = eti_get_height (eti); + + if (new_height != eti->height){ + 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]); + } +} + /* * Callback routine: invoked when the ETableModel has suffered a change */ @@ -247,7 +270,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) - eti->height = eti_get_height (eti); + eti_compute_height (eti); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } @@ -368,6 +391,7 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); + eti->table_model_row_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_row_changed", GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); @@ -547,7 +571,8 @@ eti_realize (GnomeCanvasItem *item) */ eti_realize_cell_views (eti); - eti->height = eti_get_height (eti); + eti_compute_height (eti); + eti_update (item, NULL, NULL, 0); } @@ -799,6 +824,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub return TRUE; } +static void +eti_cursor_move_left (ETableItem *eti) +{ + e_table_item_leave_edit (eti); + e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); +} + +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); +} + +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); +} + +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); +} + static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { @@ -874,35 +927,53 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if (eti->focused_col > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); - } + if (eti->focused_col > 0) + eti_cursor_move_left (eti); + return TRUE; case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); - } + if ((eti->focused_col + 1) < eti->cols) + eti_cursor_move_right (eti); return TRUE; case GDK_Up: - if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); - } + if (eti->focused_row > 0) + eti_cursor_move_up (eti); return TRUE; case GDK_Down: - if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); - } + if ((eti->focused_row + 1) < eti->rows) + eti_cursor_move_down (eti); + return TRUE; + + case GDK_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_col + 1) < eti->cols) + 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 */ + } + } + break; + default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) @@ -967,7 +1038,8 @@ eti_class_init (GtkObjectClass *object_class) item_class->draw = eti_draw; item_class->point = eti_point; item_class->event = eti_event; - + item_class->bounds = eti_bounds; + eti_class->row_selection = eti_row_selection; gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER, @@ -992,6 +1064,14 @@ eti_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableItemClass, row_selection), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); + + eti_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL); @@ -1037,7 +1117,7 @@ e_table_item_focus (ETableItem *eti, int col, int row) /* * make sure we have the Gtk Focus */ - gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas)); + gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (eti)); } void diff --git a/widgets/e-table/e-table-item.h b/widgets/e-table/e-table-item.h index e9125431b1..0867a09d6b 100644 --- a/widgets/e-table/e-table-item.h +++ b/widgets/e-table/e-table-item.h @@ -67,6 +67,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); + void (*height_changed) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); diff --git a/widgets/e-table/e-table-model.h b/widgets/e-table/e-table-model.h index fb37731a8a..2d08f3744e 100644 --- a/widgets/e-table/e-table-model.h +++ b/widgets/e-table/e-table-model.h @@ -56,5 +56,3 @@ void e_table_model_row_changed (ETableModel *e_table_model, int row) void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row); #endif /* _E_TABLE_MODEL_H_ */ - - diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c index b5f77f622b..ff81866361 100644 --- a/widgets/e-table/e-table.c +++ b/widgets/e-table/e-table.c @@ -29,17 +29,6 @@ static GtkObjectClass *e_table_parent_class; -typedef struct { - ETableModel *table; - GnomeCanvasItem *table_item; - GnomeCanvasItem *lead; -} Leaf; - -typedef struct { - -} Node; - - static void et_destroy (GtkObject *object) { @@ -122,38 +111,6 @@ e_table_setup_header (ETable *e_table) } -static Leaf * -e_table_create_leaf (ETable *e_table, ETableModel *etm, int col, int height) -{ - Leaf *leaf; - - leaf = g_new (Leaf, 1); - leaf->table = etm; - - leaf->table_item = gnome_canvas_item_new ( - gnome_canvas_root (e_table->table_canvas), - e_table_item_get_type (), - "ETableHeader", e_table->header, - "ETableModel", etm, - "x", (double) 0, - "y", (double) 0, - "drawgrid", e_table->draw_grid, - "drawfocus", e_table->draw_focus, - "spreadsheet", e_table->spreadsheet, - NULL); - - leaf->lead = e_table_group_new ( - gnome_canvas_root (e_table->table_canvas), - e_table->header, col, leaf->table_item, TRUE); - - gnome_canvas_item_set ( - leaf->lead, - "y", (double) height, - NULL); - - return leaf; -} - typedef struct { void *value; GArray *array; @@ -232,7 +189,6 @@ e_table_make_subtables (ETableModel *model, GArray *groups) ETableSubset *ss; int j; - printf ("Creating subset of %d elements\n", sub_size); tables [i] = e_table_subset_new (model, sub_size); ss = E_TABLE_SUBSET (tables [i]); @@ -244,68 +200,167 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } +typedef struct _Node Node; + +struct _Node { + Node *parent; + GnomeCanvasItem *item; + ETableModel *table_model; + GSList *children; + + guint is_leaf:1; +}; + +static Node * +leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_item != NULL); + g_assert (table_model != NULL); + g_assert (parent != NULL); + + node->item = table_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 1; + + g_assert (!parent->is_leaf); + + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), table_item); + + return node; +} + +static Node * +node_new (GnomeCanvasItem *group_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_model != NULL); + + node->children = NULL; + node->item = group_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 0; + + if (parent){ + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), group_item); + } + + return node; +} + +static Node * +e_table_create_leaf (ETable *e_table, ETableModel *etm, Node *parent) +{ + GnomeCanvasItem *table_item; + static double last_y; + Node *leaf; + + table_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (parent->item), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + leaf = leaf_new (table_item, etm, parent); + + return leaf; +} + static int -leaf_height (Leaf *leaf) +leaf_height (Node *leaf) { - return leaf->lead->y2 - leaf->lead->y1; + const GnomeCanvasItem *item = leaf->item; + + return item->y2 - item->y1; } -static Leaf * +static int +leaf_event (GnomeCanvasItem *item, GdkEvent *event) +{ + static int last_x = -1; + static int last_y = -1; + + if (event->type == GDK_BUTTON_PRESS){ + last_x = event->button.x; + last_y = event->button.y; + } else if (event->type == GDK_BUTTON_RELEASE){ + last_x = -1; + last_y = -1; + } else if (event->type == GDK_MOTION_NOTIFY){ + if (last_x == -1) + return FALSE; + + gnome_canvas_item_move (item, event->motion.x - last_x, event->motion.y - last_y); + last_x = event->motion.x; + last_y = event->motion.y; + } else + return FALSE; + return TRUE; +} + +static Node * e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, - GnomeCanvasGroup *root, int height, int *groups_list) + GnomeCanvasGroup *root, Node *parent, int *groups_list) { GArray *groups; ETableModel **tables; + ETableCol *ecol; int key_col, i; - GCompareFunc comp; - Leaf *leaf; - GnomeCanvasItem *group; - - if (groups_list) - key_col = *groups_list; - else - key_col = -1; - - if (key_col == -1){ - printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); - leaf = e_table_create_leaf (e_table, model, key_col, height); - - return leaf; - } + GnomeCanvasItem *group_item; + Node *group; + key_col = *groups_list; + g_assert (key_col != -1); + /* * Create groups */ - comp = e_table_header_get_column (header, key_col)->compare; - groups = e_table_create_groups (model, key_col, comp); + ecol = e_table_header_get_column (header, key_col); + + g_assert (ecol != NULL); + + groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - leaf = g_new0 (Leaf, 1); - - leaf->table = NULL; - leaf->table_item = NULL; - group = gnome_canvas_item_new ( - root, - gnome_canvas_group_get_type (), - NULL); - - height = 0; + group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group = node_new (group_item, model, parent); + for (i = 0; tables [i] != NULL; i++){ - printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); - - leaf = e_table_create_nodes ( - e_table, tables [i], header, GNOME_CANVAS_GROUP (group), height, - &groups_list [1]); + Node *node; - height += leaf_height (leaf); + /* + * Leafs + */ + if (groups_list [1] == -1){ + GnomeCanvasItem *item_leaf_header; + Node *leaf_header; + + item_leaf_header = e_table_group_new ( + 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); + } else { + e_table_create_nodes ( + e_table, tables [i], header, GNOME_CANVAS_GROUP (group_item), + group, &groups_list [1]); + } } - leaf->lead = e_table_group_new ( - root, - e_table->header, key_col, group, TRUE); - - return leaf; + return group; } static int * @@ -372,9 +427,9 @@ e_table_canvas_realize (GtkWidget *widget) { ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; - Leaf *leaf; int *groups; - + Node *leaf; + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); groups = group_spec_to_desc (e_table->group_spec); @@ -434,10 +489,16 @@ e_table_canvas_class_init (GtkObjectClass *object_class) e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); } +static void +e_table_canvas_init (GtkObject *canvas) +{ + GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS); +} + GtkType e_table_canvas_get_type (void); E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, - NULL, E_TABLE_CANVAS_PARENT_TYPE); + e_table_canvas_init, E_TABLE_CANVAS_PARENT_TYPE); static GnomeCanvas * e_table_canvas_new (ETable *e_table) diff --git a/widgets/e-table/e-table.h b/widgets/e-table/e-table.h index eb089781b9..e2a5a3e9d5 100644 --- a/widgets/e-table/e-table.h +++ b/widgets/e-table/e-table.h @@ -50,4 +50,4 @@ GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, END_GNOME_DECLS -#endif /* _E_TABLE_H_ */ + #endif /* _E_TABLE_H_ */ diff --git a/widgets/e-table/table-test.c b/widgets/e-table/table-test.c index 73cb22f4b1..9de673ede4 100644 --- a/widgets/e-table/table-test.c +++ b/widgets/e-table/table-test.c @@ -31,11 +31,9 @@ main (int argc, char *argv []) gnome_init ("TableTest", "TableTest", argc, argv); e_cursors_init (); -#if 0 table_browser_test (); multi_cols_test (); check_test (); -#endif e_table_test (); gtk_main (); diff --git a/widgets/e-table/test-table.c b/widgets/e-table/test-table.c index 63fd7ce271..2e64826cba 100644 --- a/widgets/e-table/test-table.c +++ b/widgets/e-table/test-table.c @@ -286,6 +286,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) gtk_container_add (GTK_CONTAINER (window), e_table); + gtk_widget_set_usize (window, 200, 200); gtk_widget_show (e_table); gtk_widget_show (window); } @@ -294,7 +295,10 @@ void e_table_test (void) { load_data (); - do_e_table_demo ("0,1,2,3,4", NULL); + + if (getenv ("DO")){ + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3,4"); + } do_e_table_demo ("0,1,2,3,4", "3"); - do_e_table_demo ("0,1,2,3,4", "3,4"); } diff --git a/widgets/table-test.c b/widgets/table-test.c index 73cb22f4b1..9de673ede4 100644 --- a/widgets/table-test.c +++ b/widgets/table-test.c @@ -31,11 +31,9 @@ main (int argc, char *argv []) gnome_init ("TableTest", "TableTest", argc, argv); e_cursors_init (); -#if 0 table_browser_test (); multi_cols_test (); check_test (); -#endif e_table_test (); gtk_main (); diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index 79fe432326..9d599f3d4c 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -221,7 +221,10 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, */ if ((px + left_len) > x2) px -= left_len - (x2-x1); - + + /* + * Draw + */ for (i = 0, p = text_wc; *p; p++, i++){ gdk_draw_text_wc ( drawable, font, gc, px, y, p, 1); diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c index 76c317369e..8765c3b83c 100644 --- a/widgets/table/e-table-group.c +++ b/widgets/table/e-table-group.c @@ -10,6 +10,7 @@ #include <config.h> #include <gtk/gtksignal.h> #include "e-table-group.h" +#include "e-table-item.h" #include <libgnomeui/gnome-canvas-rect-ellipse.h> #include "e-util.h" @@ -20,71 +21,67 @@ static GnomeCanvasGroupClass *etg_parent_class; +enum { + HEIGHT_CHANGED, + LAST_SIGNAL +}; + +static gint etg_signals [LAST_SIGNAL] = { 0, }; + static void etg_destroy (GtkObject *object) { ETableGroup *etg = E_TABLE_GROUP (object); - gtk_object_unref (GTK_OBJECT (etg->ecol)); - GTK_OBJECT_CLASS (etg_parent_class)->destroy (object); } -static int -etg_width (ETableGroup *etg) +static void +etg_dim (ETableGroup *etg, int *width, int *height) { - return e_table_header_total_width (etg->header) + GROUP_INDENT; -} + GSList *l; -static int -etg_height (ETableGroup *etg) -{ - GnomeCanvasItem *child = etg->child; + *width = *height = 0; - return TITLE_HEIGHT + (child->y2 - child->y1); -} + for (l = etg->children; l; l = l->next){ + GnomeCanvasItem *child = l->data; -static void -etg_header_changed (ETableHeader *header, ETableGroup *etg) -{ - gnome_canvas_item_set ( - etg->rect, - "x2", (double) etg_width (etg), - NULL); + *height += child->y2 - child->y1; + *width += child->x2 - child->x1; + } + + if (!etg->transparent){ + *height += TITLE_HEIGHT; + *width += GROUP_INDENT; + } } void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open) + ETableCol *ecol, gboolean open, + gboolean transparent) { gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL); - gtk_object_ref (GTK_OBJECT (header)); - - etg->header = header; - etg->col = col; - etg->ecol = e_table_header_get_column (header, col); + etg->ecol = ecol; etg->open = open; + etg->transparent = transparent; + + etg_dim (etg, &etg->width, &etg->height); - gtk_signal_connect ( - GTK_OBJECT (header), "dimension_change", - GTK_SIGNAL_FUNC (etg_header_changed), etg); - - etg->child = child; - - 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 (etg), - "y2", (double) etg_height (etg), - NULL); + 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); - +#if 0 /* * Reparent the child into our space. */ @@ -95,30 +92,151 @@ e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, "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, ETableHeader *header, int col, GnomeCanvasItem *child, int open) +e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent) { ETableGroup *etg; g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (header != NULL, NULL); - g_return_val_if_fail (child != NULL, NULL); + g_return_val_if_fail (ecol != NULL, NULL); etg = gtk_type_new (e_table_group_get_type ()); - e_table_group_construct (parent, etg, header, col, child, open); + e_table_group_construct (parent, etg, ecol, open, transparent); return GNOME_CANVAS_ITEM (etg); } static void +etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg) +{ + GSList *l; + int height = etg->transparent ? 0 : GROUP_INDENT; + gboolean move = FALSE; + + printf ("Relaying out\n"); + + for (l = etg->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 != etg->height){ + etg->height = height; + gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]); + } +} + +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_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 ("Positioning item %p at %d\n", item, height); + 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); + } + } +} + +static void etg_realize (GnomeCanvasItem *item) { ETableGroup *etg = E_TABLE_GROUP (item); + GSList *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); + } + } } static void @@ -129,8 +247,20 @@ etg_class_init (GtkObjectClass *object_class) object_class->destroy = etg_destroy; item_class->realize = etg_realize; - + item_class->update = etg_update; + etg_parent_class = gtk_type_class (PARENT_TYPE); + + etg_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed), + 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/table/e-table-group.h b/widgets/table/e-table-group.h index 18f4b710b1..468d5dd794 100644 --- a/widgets/table/e-table-group.h +++ b/widgets/table/e-table-group.h @@ -14,22 +14,50 @@ typedef struct { GnomeCanvasGroup group; - ETableHeader *header; + /* + * The ETableCol used to group this set + */ ETableCol *ecol; - int col; - int open; - GnomeCanvasItem *rect, *child; + + /* + * The canvas rectangle that contains the children + */ + GnomeCanvasItem *rect; + + /* + * Dimensions of the ETableGroup + */ + int width, height; + + /* + * State: the ETableGroup is open or closed + */ + guint open:1; + + /* + * Whether we should add indentation and open/close markers, + * or if we just act as containers of subtables. + */ + guint transparent:1; + + /* + * List of GnomeCanvasItems we stack + */ + GSList *children; } ETableGroup; typedef struct { GnomeCanvasGroupClass parent_class; + void (*height_changed) (ETableGroup *etg); } ETableGroupClass; -GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableHeader *header, - int col, GnomeCanvasItem *child, int open); +GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol, + gboolean open, gboolean transparent); void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg, - ETableHeader *header, int col, - GnomeCanvasItem *child, int open); -GtkType e_table_group_get_type (void); + ETableCol *ecol, gboolean open, gboolean transparent); + +void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child); + +GtkType e_table_group_get_type (void); #endif /* _E_TABLE_TREE_H_ */ diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index 23b72d5557..f9c5bc197d 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -26,6 +26,7 @@ static GnomeCanvasItemClass *eti_parent_class; enum { ROW_SELECTION, + HEIGHT_CHANGED, LAST_SIGNAL }; @@ -97,18 +98,12 @@ eti_unrealize_cell_views (ETableItem *eti) } -/* - * GnomeCanvasItem::update method - */ static void -eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +eti_bounds (ETableItem *eti, double *x1, double *y1, double *x2, double *y2) { - ETableItem *eti = E_TABLE_ITEM (item); double i2c [6]; ArtPoint c1, c2, i1, i2; - - if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) - (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (eti); gnome_canvas_item_i2c_affine (item, i2c); i1.x = eti->x1; @@ -122,9 +117,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) item->y1 = c1.y; item->x2 = c2.x; item->y2 = c2.y; +} - printf ("BBOX: %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2); + +/* + * GnomeCanvasItem::update method + */ +static void +eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + ETableItem *eti = E_TABLE_ITEM (item); + if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update) + (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags); + + eti_bounds (eti, &item->x1, &item->y1, &item->x2, &item->y2); gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item); } @@ -238,6 +245,22 @@ eti_get_height (ETableItem *eti) return height; } +static void +eti_compute_height (ETableItem *eti) +{ + int new_height = eti_get_height (eti); + + if (new_height != eti->height){ + 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]); + } +} + /* * Callback routine: invoked when the ETableModel has suffered a change */ @@ -247,7 +270,7 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti) eti->rows = e_table_model_row_count (eti->table_model); if (eti->cell_views) - eti->height = eti_get_height (eti); + eti_compute_height (eti); eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0); } @@ -368,6 +391,7 @@ eti_add_table_model (ETableItem *eti, ETableModel *table_model) eti->table_model_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_changed", GTK_SIGNAL_FUNC (eti_table_model_changed), eti); + eti->table_model_row_change_id = gtk_signal_connect ( GTK_OBJECT (table_model), "model_row_changed", GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti); @@ -547,7 +571,8 @@ eti_realize (GnomeCanvasItem *item) */ eti_realize_cell_views (eti); - eti->height = eti_get_height (eti); + eti_compute_height (eti); + eti_update (item, NULL, NULL, 0); } @@ -799,6 +824,34 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, doub return TRUE; } +static void +eti_cursor_move_left (ETableItem *eti) +{ + e_table_item_leave_edit (eti); + e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); +} + +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); +} + +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); +} + +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); +} + static int eti_event (GnomeCanvasItem *item, GdkEvent *e) { @@ -874,35 +927,53 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e) if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if (eti->focused_col > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row); - } + if (eti->focused_col > 0) + eti_cursor_move_left (eti); + return TRUE; case GDK_Right: if (!eti->mode_spreadsheet && eti_editing (eti)) break; - if ((eti->focused_col + 1) < eti->cols){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row); - } + if ((eti->focused_col + 1) < eti->cols) + eti_cursor_move_right (eti); return TRUE; case GDK_Up: - if (eti->focused_row > 0){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1); - } + if (eti->focused_row > 0) + eti_cursor_move_up (eti); return TRUE; case GDK_Down: - if ((eti->focused_row + 1) < eti->rows){ - e_table_item_leave_edit (eti); - e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1); - } + if ((eti->focused_row + 1) < eti->rows) + eti_cursor_move_down (eti); + return TRUE; + + case GDK_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_col + 1) < eti->cols) + 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 */ + } + } + break; + default: if (!eti_editing (eti)){ if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0) @@ -967,7 +1038,8 @@ eti_class_init (GtkObjectClass *object_class) item_class->draw = eti_draw; item_class->point = eti_point; item_class->event = eti_event; - + item_class->bounds = eti_bounds; + eti_class->row_selection = eti_row_selection; gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER, @@ -992,6 +1064,14 @@ eti_class_init (GtkObjectClass *object_class) GTK_SIGNAL_OFFSET (ETableItemClass, row_selection), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); + + eti_signals [HEIGHT_CHANGED] = + gtk_signal_new ("height_changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (ETableItemClass, height_changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL); @@ -1037,7 +1117,7 @@ e_table_item_focus (ETableItem *eti, int col, int row) /* * make sure we have the Gtk Focus */ - gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas)); + gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (eti)); } void diff --git a/widgets/table/e-table-item.h b/widgets/table/e-table-item.h index e9125431b1..0867a09d6b 100644 --- a/widgets/table/e-table-item.h +++ b/widgets/table/e-table-item.h @@ -67,6 +67,7 @@ typedef struct { GnomeCanvasItemClass parent_class; void (*row_selection) (ETableItem *eti, int row, gboolean selected); + void (*height_changed) (ETableItem *eti); } ETableItemClass; GtkType e_table_item_get_type (void); diff --git a/widgets/table/e-table-model.h b/widgets/table/e-table-model.h index fb37731a8a..2d08f3744e 100644 --- a/widgets/table/e-table-model.h +++ b/widgets/table/e-table-model.h @@ -56,5 +56,3 @@ void e_table_model_row_changed (ETableModel *e_table_model, int row) void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row); #endif /* _E_TABLE_MODEL_H_ */ - - diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index b5f77f622b..ff81866361 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -29,17 +29,6 @@ static GtkObjectClass *e_table_parent_class; -typedef struct { - ETableModel *table; - GnomeCanvasItem *table_item; - GnomeCanvasItem *lead; -} Leaf; - -typedef struct { - -} Node; - - static void et_destroy (GtkObject *object) { @@ -122,38 +111,6 @@ e_table_setup_header (ETable *e_table) } -static Leaf * -e_table_create_leaf (ETable *e_table, ETableModel *etm, int col, int height) -{ - Leaf *leaf; - - leaf = g_new (Leaf, 1); - leaf->table = etm; - - leaf->table_item = gnome_canvas_item_new ( - gnome_canvas_root (e_table->table_canvas), - e_table_item_get_type (), - "ETableHeader", e_table->header, - "ETableModel", etm, - "x", (double) 0, - "y", (double) 0, - "drawgrid", e_table->draw_grid, - "drawfocus", e_table->draw_focus, - "spreadsheet", e_table->spreadsheet, - NULL); - - leaf->lead = e_table_group_new ( - gnome_canvas_root (e_table->table_canvas), - e_table->header, col, leaf->table_item, TRUE); - - gnome_canvas_item_set ( - leaf->lead, - "y", (double) height, - NULL); - - return leaf; -} - typedef struct { void *value; GArray *array; @@ -232,7 +189,6 @@ e_table_make_subtables (ETableModel *model, GArray *groups) ETableSubset *ss; int j; - printf ("Creating subset of %d elements\n", sub_size); tables [i] = e_table_subset_new (model, sub_size); ss = E_TABLE_SUBSET (tables [i]); @@ -244,68 +200,167 @@ e_table_make_subtables (ETableModel *model, GArray *groups) return (ETableModel **) tables; } +typedef struct _Node Node; + +struct _Node { + Node *parent; + GnomeCanvasItem *item; + ETableModel *table_model; + GSList *children; + + guint is_leaf:1; +}; + +static Node * +leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_item != NULL); + g_assert (table_model != NULL); + g_assert (parent != NULL); + + node->item = table_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 1; + + g_assert (!parent->is_leaf); + + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), table_item); + + return node; +} + +static Node * +node_new (GnomeCanvasItem *group_item, ETableModel *table_model, Node *parent) +{ + Node *node = g_new (Node, 1); + + g_assert (table_model != NULL); + + node->children = NULL; + node->item = group_item; + node->parent = parent; + node->table_model = table_model; + node->is_leaf = 0; + + if (parent){ + parent->children = g_slist_append (parent->children, node); + + e_table_group_add (E_TABLE_GROUP (parent->item), group_item); + } + + return node; +} + +static Node * +e_table_create_leaf (ETable *e_table, ETableModel *etm, Node *parent) +{ + GnomeCanvasItem *table_item; + static double last_y; + Node *leaf; + + table_item = gnome_canvas_item_new ( + GNOME_CANVAS_GROUP (parent->item), + e_table_item_get_type (), + "ETableHeader", e_table->header, + "ETableModel", etm, + "drawgrid", e_table->draw_grid, + "drawfocus", e_table->draw_focus, + "spreadsheet", e_table->spreadsheet, + NULL); + + leaf = leaf_new (table_item, etm, parent); + + return leaf; +} + static int -leaf_height (Leaf *leaf) +leaf_height (Node *leaf) { - return leaf->lead->y2 - leaf->lead->y1; + const GnomeCanvasItem *item = leaf->item; + + return item->y2 - item->y1; } -static Leaf * +static int +leaf_event (GnomeCanvasItem *item, GdkEvent *event) +{ + static int last_x = -1; + static int last_y = -1; + + if (event->type == GDK_BUTTON_PRESS){ + last_x = event->button.x; + last_y = event->button.y; + } else if (event->type == GDK_BUTTON_RELEASE){ + last_x = -1; + last_y = -1; + } else if (event->type == GDK_MOTION_NOTIFY){ + if (last_x == -1) + return FALSE; + + gnome_canvas_item_move (item, event->motion.x - last_x, event->motion.y - last_y); + last_x = event->motion.x; + last_y = event->motion.y; + } else + return FALSE; + return TRUE; +} + +static Node * e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header, - GnomeCanvasGroup *root, int height, int *groups_list) + GnomeCanvasGroup *root, Node *parent, int *groups_list) { GArray *groups; ETableModel **tables; + ETableCol *ecol; int key_col, i; - GCompareFunc comp; - Leaf *leaf; - GnomeCanvasItem *group; - - if (groups_list) - key_col = *groups_list; - else - key_col = -1; - - if (key_col == -1){ - printf ("Leaf->with %d rows\n", e_table_model_row_count (model)); - leaf = e_table_create_leaf (e_table, model, key_col, height); - - return leaf; - } + GnomeCanvasItem *group_item; + Node *group; + key_col = *groups_list; + g_assert (key_col != -1); + /* * Create groups */ - comp = e_table_header_get_column (header, key_col)->compare; - groups = e_table_create_groups (model, key_col, comp); + ecol = e_table_header_get_column (header, key_col); + + g_assert (ecol != NULL); + + groups = e_table_create_groups (model, key_col, ecol->compare); tables = e_table_make_subtables (e_table->model, groups); e_table_destroy_groups (groups); - leaf = g_new0 (Leaf, 1); - - leaf->table = NULL; - leaf->table_item = NULL; - group = gnome_canvas_item_new ( - root, - gnome_canvas_group_get_type (), - NULL); - - height = 0; + group_item = e_table_group_new (root, ecol, TRUE, parent == NULL); + group = node_new (group_item, model, parent); + for (i = 0; tables [i] != NULL; i++){ - printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i])); - - leaf = e_table_create_nodes ( - e_table, tables [i], header, GNOME_CANVAS_GROUP (group), height, - &groups_list [1]); + Node *node; - height += leaf_height (leaf); + /* + * Leafs + */ + if (groups_list [1] == -1){ + GnomeCanvasItem *item_leaf_header; + Node *leaf_header; + + item_leaf_header = e_table_group_new ( + 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); + } else { + e_table_create_nodes ( + e_table, tables [i], header, GNOME_CANVAS_GROUP (group_item), + group, &groups_list [1]); + } } - leaf->lead = e_table_group_new ( - root, - e_table->header, key_col, group, TRUE); - - return leaf; + return group; } static int * @@ -372,9 +427,9 @@ e_table_canvas_realize (GtkWidget *widget) { ETableCanvas *e_table_canvas = (ETableCanvas *) widget; ETable *e_table = e_table_canvas->e_table; - Leaf *leaf; int *groups; - + Node *leaf; + GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget); groups = group_spec_to_desc (e_table->group_spec); @@ -434,10 +489,16 @@ e_table_canvas_class_init (GtkObjectClass *object_class) e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE); } +static void +e_table_canvas_init (GtkObject *canvas) +{ + GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS); +} + GtkType e_table_canvas_get_type (void); E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init, - NULL, E_TABLE_CANVAS_PARENT_TYPE); + e_table_canvas_init, E_TABLE_CANVAS_PARENT_TYPE); static GnomeCanvas * e_table_canvas_new (ETable *e_table) diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h index eb089781b9..e2a5a3e9d5 100644 --- a/widgets/table/e-table.h +++ b/widgets/table/e-table.h @@ -50,4 +50,4 @@ GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm, END_GNOME_DECLS -#endif /* _E_TABLE_H_ */ + #endif /* _E_TABLE_H_ */ diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c index 73cb22f4b1..9de673ede4 100644 --- a/widgets/table/table-test.c +++ b/widgets/table/table-test.c @@ -31,11 +31,9 @@ main (int argc, char *argv []) gnome_init ("TableTest", "TableTest", argc, argv); e_cursors_init (); -#if 0 table_browser_test (); multi_cols_test (); check_test (); -#endif e_table_test (); gtk_main (); diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c index 63fd7ce271..2e64826cba 100644 --- a/widgets/table/test-table.c +++ b/widgets/table/test-table.c @@ -286,6 +286,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) gtk_container_add (GTK_CONTAINER (window), e_table); + gtk_widget_set_usize (window, 200, 200); gtk_widget_show (e_table); gtk_widget_show (window); } @@ -294,7 +295,10 @@ void e_table_test (void) { load_data (); - do_e_table_demo ("0,1,2,3,4", NULL); + + if (getenv ("DO")){ + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3,4"); + } do_e_table_demo ("0,1,2,3,4", "3"); - do_e_table_demo ("0,1,2,3,4", "3,4"); } diff --git a/widgets/test-table.c b/widgets/test-table.c index 63fd7ce271..2e64826cba 100644 --- a/widgets/test-table.c +++ b/widgets/test-table.c @@ -286,6 +286,7 @@ do_e_table_demo (const char *col_spec, const char *group_spec) gtk_container_add (GTK_CONTAINER (window), e_table); + gtk_widget_set_usize (window, 200, 200); gtk_widget_show (e_table); gtk_widget_show (window); } @@ -294,7 +295,10 @@ void e_table_test (void) { load_data (); - do_e_table_demo ("0,1,2,3,4", NULL); + + if (getenv ("DO")){ + do_e_table_demo ("0,1,2,3,4", NULL); + do_e_table_demo ("0,1,2,3,4", "3,4"); + } do_e_table_demo ("0,1,2,3,4", "3"); - do_e_table_demo ("0,1,2,3,4", "3,4"); } |