aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/table')
-rw-r--r--widgets/table/e-cell-checkbox.c4
-rw-r--r--widgets/table/e-cell-checkbox.h2
-rw-r--r--widgets/table/e-cell-text.c14
-rw-r--r--widgets/table/e-cell-toggle.c22
-rw-r--r--widgets/table/e-cell-toggle.h8
-rw-r--r--widgets/table/e-cell.c6
-rw-r--r--widgets/table/e-cell.h7
-rw-r--r--widgets/table/e-table-header-item.c2
-rw-r--r--widgets/table/e-table-header.c2
-rw-r--r--widgets/table/e-table-item.c11
-rw-r--r--widgets/table/e-table-subset.c75
-rw-r--r--widgets/table/e-table-subset.h3
-rw-r--r--widgets/table/e-table.c483
-rw-r--r--widgets/table/e-table.h51
-rw-r--r--widgets/table/sample.table3
-rw-r--r--widgets/table/table-test.c3
-rw-r--r--widgets/table/test-check.c4
-rw-r--r--widgets/table/test-cols.c5
-rw-r--r--widgets/table/test-table.c59
19 files changed, 694 insertions, 70 deletions
diff --git a/widgets/table/e-cell-checkbox.c b/widgets/table/e-cell-checkbox.c
index 73620b9ce4..6e4b597abf 100644
--- a/widgets/table/e-cell-checkbox.c
+++ b/widgets/table/e-cell-checkbox.c
@@ -34,11 +34,11 @@ e_cell_checkbox_class_init (GtkObjectClass *object_class)
E_MAKE_TYPE(e_cell_checkbox, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE);
ECell *
-e_cell_checkbox_new (ETableModel *etm)
+e_cell_checkbox_new (void)
{
ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ());
- e_cell_toggle_construct (E_CELL_TOGGLE (eccb), etm, 2, 2, checks);
+ e_cell_toggle_construct (E_CELL_TOGGLE (eccb), 2, 2, checks);
return (ECell *) eccb;
}
diff --git a/widgets/table/e-cell-checkbox.h b/widgets/table/e-cell-checkbox.h
index 6afca6bde2..969e4a5edc 100644
--- a/widgets/table/e-cell-checkbox.h
+++ b/widgets/table/e-cell-checkbox.h
@@ -18,7 +18,7 @@ typedef struct {
} ECellCheckboxClass;
GtkType e_cell_checkbox_get_type (void);
-ECell *e_cell_checkbox_new (ETableModel *model);
+ECell *e_cell_checkbox_new (void);
#endif /* _E_CELL_CHECKBOX_H_ */
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index 828be6cc29..79fe432326 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -13,6 +13,7 @@
#include <gtk/gtksignal.h>
#include <gdk/gdkkeysyms.h>
#include <libgnomeui/gnome-canvas.h>
+#include <stdio.h>
#include "e-cell-text.h"
#include "e-util.h"
#include "e-table-item.h"
@@ -62,7 +63,7 @@ ect_accept_edits (ECellTextView *text_view)
const char *text = gtk_entry_get_text (text_view->edit->entry);
CellEdit *edit = text_view->edit;
- e_table_model_set_value_at (text_view->eti->table_model, edit->model_col, edit->row, text);
+ e_table_model_set_value_at (text_view->cell_view.table_model, edit->model_col, edit->row, text);
}
/*
@@ -100,7 +101,7 @@ ect_cancel_edit (ECellTextView *text_view)
* ECell::realize method
*/
static ECellView *
-ect_realize (ECell *ecell, void *view)
+ect_realize (ECell *ecell, ETableModel *table_model, void *view)
{
ECellText *ect = E_CELL_TEXT (ecell);
ECellTextView *text_view = g_new0 (ECellTextView, 1);
@@ -108,6 +109,8 @@ ect_realize (ECell *ecell, void *view)
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
text_view->cell_view.ecell = ecell;
+ text_view->cell_view.table_model = table_model;
+
text_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window);
if (ect->font_name){
GdkFont *f;
@@ -123,7 +126,7 @@ ect_realize (ECell *ecell, void *view)
text_view->eti = eti;
text_view->canvas = canvas;
-
+
return (ECellView *)text_view;
}
@@ -156,7 +159,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
ECellTextView *text_view = (ECellTextView *) ecell_view;
GtkWidget *w = GTK_WIDGET (text_view->canvas);
GdkRectangle rect;
- const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row);
+ const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row);
GdkFont *font = text_view->font;
const int height = font->ascent + font->descent;
int xoff;
@@ -389,7 +392,7 @@ static void *
ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
{
ECellTextView *text_view = (ECellTextView *) ecell_view;
- const char *str = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row);
+ const char *str = e_table_model_value_at (ecell_view->table_model, model_col, row);
CellEdit *edit;
edit = g_new (CellEdit, 1);
@@ -476,7 +479,6 @@ e_cell_text_new (ETableModel *etm, const char *fontname, GtkJustification justif
ect->font_name = g_strdup (fontname);
ect->justify = justify;
- E_CELL (ect)->table_model = etm;
return (ECell *) ect;
}
diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c
index ec6fa38a38..dbe5fe5cbd 100644
--- a/widgets/table/e-cell-toggle.c
+++ b/widgets/table/e-cell-toggle.c
@@ -38,17 +38,18 @@ etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row)
* ECell::realize method
*/
static ECellView *
-etog_realize (ECell *ecell, void *view)
+etog_realize (ECell *ecell, ETableModel *table_model, void *view)
{
ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1);
ETableItem *eti = E_TABLE_ITEM (view);
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
toggle_view->cell_view.ecell = ecell;
+ toggle_view->cell_view.table_model = table_model;
toggle_view->eti = eti;
toggle_view->canvas = canvas;
toggle_view->gc = gdk_gc_new (GTK_WIDGET (canvas)->window);
-
+
return (ECellView *) toggle_view;
}
@@ -80,7 +81,7 @@ etog_draw (ECellView *ecell_view, GdkDrawable *drawable,
ArtPixBuf *art;
int x, y, width, height;
const int value = GPOINTER_TO_INT (
- e_table_model_value_at (ecell_view->ecell->table_model, model_col, row));
+ e_table_model_value_at (ecell_view->table_model, model_col, row));
if (value >= toggle->n_states){
g_warning ("Value from the table model is %d, the states we support are [0..%d)\n",
@@ -172,7 +173,8 @@ etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int r
if (value >= toggle->n_states)
value = 0;
- e_table_model_set_value_at (ecell->table_model, model_col, row, GINT_TO_POINTER (value));
+ e_table_model_set_value_at (toggle_view->cell_view.table_model,
+ model_col, row, GINT_TO_POINTER (value));
etog_queue_redraw (toggle_view, view_col, row);
}
@@ -183,7 +185,7 @@ static gint
etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row)
{
ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
- void *_value = e_table_model_value_at (ecell_view->ecell->table_model, model_col, row);
+ void *_value = e_table_model_value_at (ecell_view->table_model, model_col, row);
const int value = GPOINTER_TO_INT (_value);
switch (event->type){
@@ -248,13 +250,11 @@ e_cell_toggle_class_init (GtkObjectClass *object_class)
E_MAKE_TYPE(e_cell_toggle, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE);
void
-e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+e_cell_toggle_construct (ECellToggle *etog, int border, int n_states, GdkPixbuf **images)
{
int max_height = 0;
int i;
- E_CELL (etog)->table_model = etm;
-
etog->border = border;
etog->n_states = n_states;
@@ -272,11 +272,13 @@ e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm, int border, int n_
}
ECell *
-e_cell_toggle_new (ETableModel *etm, int border, int n_states, GdkPixbuf **images)
+e_cell_toggle_new (int border, int n_states, GdkPixbuf **images)
{
ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ());
- e_cell_toggle_construct (etog, etm, border, n_states, images);
+ e_cell_toggle_construct (etog, border, n_states, images);
return (ECell *) etog;
}
+
+
diff --git a/widgets/table/e-cell-toggle.h b/widgets/table/e-cell-toggle.h
index 2a5b6adc18..d5773b454a 100644
--- a/widgets/table/e-cell-toggle.h
+++ b/widgets/table/e-cell-toggle.h
@@ -26,11 +26,9 @@ typedef struct {
} ECellToggleClass;
GtkType e_cell_toggle_get_type (void);
-ECell *e_cell_toggle_new (ETableModel *model, int border,
- int n_states,
- GdkPixbuf **images);
-void e_cell_toggle_construct (ECellToggle *etog, ETableModel *etm,
- int border, int n_states, GdkPixbuf **images);
+ECell *e_cell_toggle_new (int border, int n_states, GdkPixbuf **images);
+void e_cell_toggle_construct (ECellToggle *etog, int border,
+ int n_states, GdkPixbuf **images);
#endif /* _E_CELL_TOGGLE_H_ */
diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c
index a4a03655dc..4495bbb1a7 100644
--- a/widgets/table/e-cell.c
+++ b/widgets/table/e-cell.c
@@ -13,7 +13,7 @@
#define PARENT_TYPE gtk_object_get_type()
static ECellView *
-ec_realize (ECell *e_cell, void *view)
+ec_realize (ECell *e_cell, ETableModel *table_model, void *view)
{
return NULL;
}
@@ -110,10 +110,10 @@ e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_co
}
ECellView *
-e_cell_realize (ECell *ecell, void *view)
+e_cell_realize (ECell *ecell, ETableModel *table_model, void *view)
{
return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->realize (
- ecell, view);
+ ecell, table_model, view);
}
void
diff --git a/widgets/table/e-cell.h b/widgets/table/e-cell.h
index f72f97e8dd..23173a586c 100644
--- a/widgets/table/e-cell.h
+++ b/widgets/table/e-cell.h
@@ -15,11 +15,12 @@ typedef struct _ECellView ECellView;
struct _ECell {
GtkObject object;
- ETableModel *table_model;
};
struct _ECellView {
ECell *ecell;
+ ETableModel *table_model;
+
gint focus_x1, focus_y1, focus_x2, focus_y2;
gint focus_col, focus_row;
};
@@ -29,7 +30,7 @@ struct _ECellView {
typedef struct {
GtkObjectClass parent_class;
- ECellView *(*realize) (ECell *ecell, void *view);
+ ECellView *(*realize) (ECell *ecell, ETableModel *table_model, void *view);
void (*unrealize) (ECellView *e_cell_view);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
int model_col, int view_col, int row,
@@ -46,7 +47,7 @@ typedef struct {
GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row);
-ECellView *e_cell_realize (ECell *ecell, void *view);
+ECellView *e_cell_realize (ECell *ecell, ETableModel *table_model, void *view);
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,
diff --git a/widgets/table/e-table-header-item.c b/widgets/table/e-table-header-item.c
index 0b5be9b84a..7cea9ae7a0 100644
--- a/widgets/table/e-table-header-item.c
+++ b/widgets/table/e-table-header-item.c
@@ -334,8 +334,6 @@ ethi_drag_motion (GtkObject *canvas, GdkDragContext *context,
static void
ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi)
{
- printf ("Ending\n");
-
ethi_remove_drop_marker (ethi);
ethi_remove_destroy_marker (ethi);
ethi->drag_col = -1;
diff --git a/widgets/table/e-table-header.c b/widgets/table/e-table-header.c
index 375fd34c5d..32078d9a78 100644
--- a/widgets/table/e-table-header.c
+++ b/widgets/table/e-table-header.c
@@ -126,7 +126,7 @@ e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
g_return_if_fail (E_IS_TABLE_COL (tc));
- g_return_if_fail (pos >= 0 && pos <= eth->col_count);
+ g_return_if_fail (pos >= -1 && pos <= eth->col_count);
if (pos == -1)
pos = eth->col_count;
diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c
index bdeda14a7b..d0a0ad8cba 100644
--- a/widgets/table/e-table-item.c
+++ b/widgets/table/e-table-item.c
@@ -73,7 +73,7 @@ eti_realize_cell_views (ETableItem *eti)
for (i = 0; i < eti->n_cells; i++){
ETableCol *col = e_table_header_get_column (eti->header, i);
- eti->cell_views [i] = e_cell_realize (col->ecell, eti);
+ eti->cell_views [i] = e_cell_realize (col->ecell, eti->table_model, eti);
}
}
@@ -91,6 +91,7 @@ eti_unrealize_cell_views (ETableItem *eti)
eti->cell_views [i] = NULL;
}
g_free (eti->cell_views);
+ eti->cell_views = NULL;
eti->n_cells = 0;
}
@@ -368,8 +369,12 @@ eti_header_structure_changed (ETableHeader *eth, ETableItem *eti)
eti->cols = e_table_header_count (eti->header);
eti->width = e_table_header_total_width (eti->header);
- eti_unrealize_cell_views (eti);
- eti_realize_cell_views (eti);
+
+ if (eti->cell_views){
+ eti_unrealize_cell_views (eti);
+ eti_realize_cell_views (eti);
+ }
+
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
eti_request_redraw (eti);
diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c
index 41763d309b..88f5c18c85 100644
--- a/widgets/table/e-table-subset.c
+++ b/widgets/table/e-table-subset.c
@@ -7,6 +7,8 @@
* (C) 1999 Helix Code, Inc.
*/
#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
#include "e-util.h"
#include "e-table-subset.h"
@@ -36,20 +38,12 @@ etss_column_count (ETableModel *etm)
return e_table_model_column_count (etss->source);
}
-static const char *
-etss_column_name (ETableModel *etm, int col)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_column_name (etss->source, col);
-}
-
static int
etss_row_count (ETableModel *etm)
{
ETableSubset *etss = (ETableSubset *)etm;
- return e_table_model_row_count (etss->source);
+ return etss->n_map;
}
static void *
@@ -61,7 +55,7 @@ etss_value_at (ETableModel *etm, int col, int row)
}
static void
-etss_set_value_at (ETableModel *etm, int col, int row, void *val)
+etss_set_value_at (ETableModel *etm, int col, int row, const void *val)
{
ETableSubset *etss = (ETableSubset *)etm;
@@ -76,14 +70,6 @@ etss_is_cell_editable (ETableModel *etm, int col, int row)
return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]);
}
-static int
-etss_row_height (ETableModel *etm, int row)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_row_height (etss->source, etss->map_table [row]);
-}
-
static void
etss_class_init (GtkObjectClass *klass)
{
@@ -94,25 +80,58 @@ etss_class_init (GtkObjectClass *klass)
klass->destroy = etss_destroy;
table_class->column_count = etss_column_count;
- table_class->column_name = etss_column_name;
table_class->row_count = etss_row_count;
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->row_height = etss_row_height;
-
}
E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE);
+static void
+etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss)
+{
+ 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;
+ }
+ }
+}
+
+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;
+ }
+ }
+}
+
ETableModel *
e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals)
{
unsigned int *buffer;
int i;
- buffer = (unsigned int *) malloc (sizeof (unsigned int *) * nvals);
- if (buffer = NULL)
+ buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals);
+ if (buffer == NULL)
return NULL;
etss->map_table = buffer;
etss->n_map = nvals;
@@ -123,6 +142,14 @@ e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals)
for (i = 0; i < nvals; i++)
etss->map_table [i] = i;
+ gtk_signal_connect (GTK_OBJECT (source), "model_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
+ gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
+ gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
+ GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
+
+ return E_TABLE_MODEL (etss);
}
ETableModel *
@@ -147,5 +174,5 @@ e_table_subset_get_toplevel (ETableSubset *table)
if (E_IS_TABLE_SUBSET (table->source))
return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source));
else
- return table->subset;
+ return table->source;
}
diff --git a/widgets/table/e-table-subset.h b/widgets/table/e-table-subset.h
index 66d11e9658..314f28aea6 100644
--- a/widgets/table/e-table-subset.h
+++ b/widgets/table/e-table-subset.h
@@ -26,6 +26,7 @@ GtkType e_table_subset_get_type (void);
ETableModel *e_table_subset_new (ETableModel *etm, int n_vals);
ETableModel *e_table_subset_construct (ETableSubset *ets, ETableModel *source, int nvals);
-ETableModel *e_table_subset_get_toplevel (ETableModel *table_model);
+ETableModel *e_table_subset_get_toplevel (ETableSubset *table_model);
#endif /* _E_TABLE_SUBSET_H_ */
+
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 3b13e87d6b..f9a41a38fc 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -7,16 +7,491 @@
* Copyright 1999, Helix Code, Inc
*/
#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <alloca.h>
+#include <stdio.h>
#include <libgnomeui/gnome-canvas.h>
+#include <gtk/gtksignal.h>
#include "e-table.h"
#include "e-util.h"
+#include "e-table-header-item.h"
+#include "e-table-subset.h"
+#include "e-table-item.h"
-#define PARENT_OBJECT_TYPE gnome_canvas_get_type ()
+#define COLUMN_HEADER_HEIGHT 16
+#define TITLE_HEIGHT 16
+#define GROUP_INDENT 10
-E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, NULL, PARENT_TYPE);
+#define PARENT_TYPE gtk_table_get_type ()
-ETable *
-e_table_new (ETableHeader *eth, ETableModel *etm)
+static GtkObjectClass *e_table_parent_class;
+
+typedef struct {
+ ETableModel *table;
+ GnomeCanvasItem *table_item;
+ GnomeCanvasItem *rect;
+} Leaf;
+
+typedef struct {
+} Node;
+
+
+static void
+et_destroy (GtkObject *object)
+{
+ ETable *et = E_TABLE (object);
+
+ gtk_object_unref (GTK_OBJECT (et->model));
+ 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);
+}
+
+static void
+e_table_init (GtkObject *object)
+{
+ ETable *e_table = E_TABLE (object);
+
+ e_table->draw_grid = 1;
+ e_table->draw_focus = 1;
+ e_table->spreadsheet = 1;
+}
+
+static ETableHeader *
+e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols)
+{
+ ETableHeader *nh;
+ char *copy = alloca (strlen (cols) + 1);
+ char *p, *state;
+ 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);
+
+ copy = NULL;
+ if (col >= max_cols)
+ continue;
+
+ e_table_header_add_column (nh, e_table_header_get_column (full_header, col), -1);
+ }
+
+ return nh;
+}
+
+static void
+e_table_setup_header (ETable *e_table)
+{
+ e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ());
+
+ gtk_widget_show (GTK_WIDGET (e_table->header_canvas));
+
+ e_table->header_item = gnome_canvas_item_new (
+ gnome_canvas_root (e_table->header_canvas),
+ e_table_header_item_get_type (),
+ "ETableHeader", e_table->header,
+ "x", 0,
+ "y", 0,
+ NULL);
+
+ gtk_widget_set_usize (GTK_WIDGET (e_table->header_canvas), -1, COLUMN_HEADER_HEIGHT);
+ g_warning ("Aqui");
+ e_table->header_canvas = 0;
+
+ gtk_table_attach (
+ GTK_TABLE (e_table), GTK_WIDGET (e_table->header_canvas),
+ 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+
+}
+
+static Leaf *
+e_table_create_leaf (ETable *e_table, int x_off, int y_off, ETableModel *etm)
+{
+ Leaf *leaf;
+ int height;
+
+ 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", x_off + GROUP_INDENT,
+ "y", y_off + TITLE_HEIGHT,
+ "drawgrid", e_table->draw_grid,
+ "drawfocus", e_table->draw_focus,
+ "spreadsheet", e_table->spreadsheet,
+ NULL);
+
+ height = E_TABLE_ITEM (leaf->table_item)->height;
+
+ leaf->rect = gnome_canvas_item_new (
+ gnome_canvas_root (e_table->table_canvas),
+ gnome_canvas_rect_get_type (),
+ "x1", (double) x_off,
+ "y1", (double) y_off,
+ "x2", (double) x_off + e_table->gen_header_width + GROUP_INDENT,
+ "y2", (double) y_off + TITLE_HEIGHT + height,
+ "fill_color", "gray",
+ "outline_color", "gray20",
+ NULL);
+ gnome_canvas_item_lower (leaf->rect, 1);
+
+ return leaf;
+}
+
+typedef struct {
+ void *value;
+ GArray *array;
+} group_key_t;
+
+static GArray *
+e_table_create_groups (ETableModel *etm, int key_col, GCompareFunc comp)
+{
+ GArray *groups;
+ const int rows = e_table_model_row_count (etm);
+ int row, i;
+
+ groups = g_array_new (FALSE, FALSE, sizeof (group_key_t));
+
+ for (row = 0; row < rows; row++){
+ void *val = e_table_model_value_at (etm, key_col, row);
+ const int n_groups = groups->len;
+
+ /*
+ * Should replace this with a bsearch later
+ */
+ for (i = 0; i < n_groups; i++){
+ group_key_t *g = &g_array_index (groups, group_key_t, i);
+
+ if ((*comp) (g->value, val)){
+ g_array_append_val (g->array, row);
+ break;
+ }
+ }
+ if (i != n_groups)
+ continue;
+
+ /*
+ * We need to create a new group
+ */
+ {
+ group_key_t gk;
+
+ gk.value = val;
+ gk.array = g_array_new (FALSE, FALSE, sizeof (int));
+
+ g_array_append_val (gk.array, row);
+ g_array_append_val (groups, gk);
+ }
+ }
+
+ return groups;
+}
+
+static void
+e_table_destroy_groups (GArray *groups)
+{
+ const int n = groups->len;
+ int i;
+
+ for (i = 0; i < n; i++){
+ group_key_t *g = &g_array_index (groups, group_key_t, i);
+
+ g_array_free (g->array, TRUE);
+ }
+ g_array_free (groups, TRUE);
+}
+
+static ETableModel **
+e_table_make_subtables (ETableModel *model, GArray *groups)
+{
+ const int n_groups = groups->len;
+ ETableModel **tables;
+ int i;
+
+ tables = g_new (ETableModel *, n_groups+1);
+
+ for (i = 0; i < n_groups; i++){
+ group_key_t *g = &g_array_index (groups, group_key_t, i);
+ const int sub_size = g->array->len;
+ 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]);
+
+ for (j = 0; j < sub_size; j++)
+ ss->map_table [j] = g_array_index (g->array, int, j);
+ }
+ tables [i] = NULL;
+
+ return (ETableModel **) tables;
+}
+
+static int
+leaf_height (Leaf *leaf)
+{
+ return E_TABLE_ITEM (leaf->table_item)->height + TITLE_HEIGHT;
+}
+
+static int
+e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header,
+ GnomeCanvasGroup *root, int x_off, int y_off,
+ int *groups_list)
+{
+ GArray *groups;
+ ETableModel **tables;
+ int key_col;
+ int height, i;
+ GCompareFunc comp;
+
+ if (groups_list)
+ key_col = *groups_list;
+ else
+ key_col = -1;
+
+ if (key_col == -1){
+ Leaf *leaf;
+
+ printf ("Leaf->with %d rows\n", e_table_model_row_count (model));
+ leaf = e_table_create_leaf (e_table, x_off, y_off, model);
+
+ {
+ static int warn_shown;
+
+ if (!warn_shown){
+ g_warning ("Leak");
+ warn_shown = 1;
+ }
+ }
+ return leaf_height (leaf);
+ }
+
+ /*
+ * Create groups
+ */
+ comp = e_table_header_get_column (header, key_col)->compare;
+ groups = e_table_create_groups (model, key_col, comp);
+ tables = e_table_make_subtables (e_table->model, groups);
+ e_table_destroy_groups (groups);
+
+ height = 0;
+ for (i = 0; tables [i] != NULL; i++){
+ printf ("Creating->%d with %d rows\n", i, e_table_model_row_count (tables [i]));
+ height += e_table_create_nodes (
+ e_table, tables [i], header, root,
+ x_off + 20,
+ y_off + height, &groups_list [1]);
+ }
+
+ return height;
+}
+
+static int *
+group_spec_to_desc (const char *group_spec)
{
+ int a_size = 10;
+ int *elements;
+ char *p, *copy, *follow;
+ int n_elements = 0;
+
+ if (group_spec == NULL)
+ return NULL;
+
+ elements = g_new (int, a_size);
+ copy = alloca (strlen (group_spec) + 1);
+ strcpy (copy, group_spec);
+
+ while ((p = strtok_r (copy, ",", &follow)) != NULL){
+ elements [n_elements] = atoi (p);
+ ++n_elements;
+ if (n_elements+1 == a_size){
+ int *new_e;
+
+ n_elements += 10;
+ new_e = g_renew (int, elements, n_elements);
+ if (new_e == NULL){
+ g_free (elements);
+ return NULL;
+ }
+ elements = new_e;
+ }
+ copy = NULL;
+ }
+
+ /* Tag end */
+ elements [n_elements] = -1;
+
+ return elements;
+}
+
+/*
+ * The ETableCanvas object is just used to enable us to
+ * hook up to the realize/unrealize phases of the canvas
+ * initialization (as laying out the subtables requires us to
+ * know the actual size of the subtables we are inserting
+ */
+
+#define E_TABLE_CANVAS_PARENT_TYPE gnome_canvas_get_type ()
+
+typedef struct {
+ GnomeCanvas base;
+
+ ETable *e_table;
+} ETableCanvas;
+
+typedef struct {
+ GnomeCanvasClass base_class;
+} ETableCanvasClass;
+
+static GnomeCanvasClass *e_table_canvas_parent_class;
+
+static void
+e_table_canvas_realize (GtkWidget *widget)
+{
+ ETableCanvas *e_table_canvas = (ETableCanvas *) widget;
+ ETable *e_table = e_table_canvas->e_table;
+ int *groups;
+ int height;
+
+ GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget);
+
+ groups = group_spec_to_desc (e_table->group_spec);
+
+ e_table->root = gnome_canvas_item_new (
+ GNOME_CANVAS_GROUP (e_table->table_canvas->root),
+ gnome_canvas_group_get_type (),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+
+ e_table->gen_header_width = e_table_header_total_width (e_table->header);
+
+ height = e_table_create_nodes (
+ e_table, e_table->model,
+ e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, 0, groups);
+
+ {
+ static int warn_shown;
+
+ if (!warn_shown){
+ g_warning ("Precompute the width, and update on model changes");
+ warn_shown = 1;
+ }
+ }
+
+ gnome_canvas_set_scroll_region (
+ GNOME_CANVAS (e_table_canvas),
+ 0, 0,
+ e_table_header_total_width (e_table->header) + 200,
+ height);
+
+ if (groups)
+ g_free (groups);
+}
+
+static void
+e_table_canvas_unrealize (GtkWidget *widget)
+{
+ ETableCanvas *e_table_canvas = (ETableCanvas *) widget;
+ ETable *e_table = e_table_canvas->e_table;
+
+ gtk_object_destroy (GTK_OBJECT (e_table->root));
+ e_table->root = NULL;
+
+ GTK_WIDGET_CLASS (e_table_canvas_parent_class)->unrealize (widget);
+}
+
+static void
+e_table_canvas_class_init (GtkObjectClass *object_class)
+{
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) object_class;
+
+ widget_class->realize = e_table_canvas_realize;
+ widget_class->unrealize = e_table_canvas_unrealize;
+
+ e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE);
+}
+
+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);
+
+static GnomeCanvas *
+e_table_canvas_new (ETable *e_table)
+{
+ ETableCanvas *e_table_canvas;
+
+ e_table_canvas = gtk_type_new (e_table_canvas_get_type ());
+ e_table_canvas->e_table = e_table;
+
+ return GNOME_CANVAS (e_table_canvas);
+}
+
+static void
+e_table_setup_table (ETable *e_table)
+{
+ e_table->table_canvas = e_table_canvas_new (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);
+}
+
+void
+e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm,
+ const char *cols_spec, const char *group_spec)
+{
+ GTK_TABLE (e_table)->homogeneous = FALSE;
+
+ gtk_table_resize (GTK_TABLE (e_table), 1, 2);
+
+ e_table->full_header = full_header;
+ gtk_object_ref (GTK_OBJECT (full_header));
+
+ e_table->model = etm;
+ gtk_object_ref (GTK_OBJECT (etm));
+
+ e_table->header = e_table_make_header (e_table, full_header, cols_spec);
+
+ e_table_setup_header (e_table);
+ e_table_setup_table (e_table);
+
+ e_table->group_spec = g_strdup (group_spec);
+
}
+GtkWidget *
+e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_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);
+
+ return (GtkWidget *) e_table;
+}
+
+static void
+e_table_class_init (GtkObjectClass *object_class)
+{
+ e_table_parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = et_destroy;
+}
+
+E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, e_table_init, PARENT_TYPE);
+
diff --git a/widgets/table/e-table.h b/widgets/table/e-table.h
index 0847ddde6c..eb089781b9 100644
--- a/widgets/table/e-table.h
+++ b/widgets/table/e-table.h
@@ -1,6 +1,53 @@
#ifndef _E_TABLE_H_
#define _E_TABLE_H_
-GtkType e_table_get_type (void);
-ETable *
+#include <libgnomeui/gnome-canvas.h>
+#include <gtk/gtktable.h>
+#include "e-table-model.h"
+#include "e-table-header.h"
+
+BEGIN_GNOME_DECLS
+
+#define E_TABLE_TYPE (e_table_get_type ())
+#define E_TABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_TYPE, ETable))
+#define E_TABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_TYPE, ETableClass))
+#define E_IS_TABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_TYPE))
+#define E_IS_TABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_TYPE))
+
+typedef struct {
+ GtkTable parent;
+
+ ETableModel *model;
+
+ ETableHeader *full_header, *header;
+
+ GnomeCanvas *header_canvas, *table_canvas;
+
+ GnomeCanvasItem *header_item, *root;
+
+ guint draw_grid:1;
+ guint draw_focus:1;
+ guint spreadsheet:1;
+
+ char *group_spec;
+
+ /*
+ * Used during table generation
+ */
+ int gen_header_width;
+} ETable;
+
+typedef struct {
+ GtkTableClass parent_class;
+} ETableClass;
+
+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);
+GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm,
+ const char *cols_spec, const char *group_spec);
+
+
+END_GNOME_DECLS
+
#endif /* _E_TABLE_H_ */
diff --git a/widgets/table/sample.table b/widgets/table/sample.table
index 2cb09d7f1f..45c8ff0691 100644
--- a/widgets/table/sample.table
+++ b/widgets/table/sample.table
@@ -5,4 +5,7 @@ c1.c c2.c a.c tit-1 DorkB
c1.d c2.d a.d tit-2 ADork
c1.e c2.e a.e tit-1 DorkC
c1.f c2.f a.f tit-2 UDork
+c1.g c2.g a.g tit-3 Dork---
+j k k tit-1 DorkA
+
diff --git a/widgets/table/table-test.c b/widgets/table/table-test.c
index e60dd893fe..9de673ede4 100644
--- a/widgets/table/table-test.c
+++ b/widgets/table/table-test.c
@@ -10,6 +10,7 @@
#include <fcntl.h>
#include <gnome.h>
#include "e-cursors.h"
+#include "table-test.h"
int
main (int argc, char *argv [])
@@ -33,6 +34,8 @@ main (int argc, char *argv [])
table_browser_test ();
multi_cols_test ();
check_test ();
+ e_table_test ();
+
gtk_main ();
e_cursors_shutdown ();
diff --git a/widgets/table/test-check.c b/widgets/table/test-check.c
index 9968426327..9e003ce9a1 100644
--- a/widgets/table/test-check.c
+++ b/widgets/table/test-check.c
@@ -16,6 +16,8 @@
#include "e-cell-text.h"
#include "e-cell-checkbox.h"
+#include "table-test.h"
+
#define LINES 4
static struct {
@@ -105,7 +107,7 @@ check_test (void)
cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
- cell_image_check = e_cell_checkbox_new (e_table_model);
+ cell_image_check = e_cell_checkbox_new ();
col_0 = e_table_col_new (0, "", 18, 18, cell_image_check, g_int_equal, TRUE);
e_table_header_add_column (e_table_header, col_0, 0);
diff --git a/widgets/table/test-cols.c b/widgets/table/test-cols.c
index 4406c6b3b9..b7979c2f3d 100644
--- a/widgets/table/test-cols.c
+++ b/widgets/table/test-cols.c
@@ -16,6 +16,8 @@
#include "e-cell-text.h"
#include "e-cell-toggle.h"
+#include "table-test.h"
+
#define LINES 4
static struct {
@@ -90,7 +92,6 @@ multi_cols_test (void)
ETableHeader *e_table_header, *e_table_header_multiple;
ETableCol *col_0, *col_1;
ECell *cell_left_just, *cell_image_toggle;
- int i;
gtk_widget_push_visual (gdk_rgb_get_visual ());
gtk_widget_push_colormap (gdk_rgb_get_cmap ());
@@ -114,7 +115,7 @@ multi_cols_test (void)
images [1] = gdk_pixbuf_new_from_file ("image2.png");
images [2] = gdk_pixbuf_new_from_file ("image3.png");
- cell_image_toggle = e_cell_toggle_new (e_table_model, 0, 3, images);
+ cell_image_toggle = e_cell_toggle_new (0, 3, images);
for (i = 0; i < 3; i++)
gdk_pixbuf_unref (images [i]);
diff --git a/widgets/table/test-table.c b/widgets/table/test-table.c
index 04c40959af..83a130d72a 100644
--- a/widgets/table/test-table.c
+++ b/widgets/table/test-table.c
@@ -14,6 +14,9 @@
#include "e-table-item.h"
#include "e-cursors.h"
#include "e-cell-text.h"
+#include "e-table.h"
+
+#include "table-test.h"
char buffer [1024];
char **column_labels;
@@ -97,6 +100,16 @@ load_data ()
{
int i;
+ {
+ static int loaded;
+
+ if (loaded)
+ return;
+
+ loaded = TRUE;
+ }
+
+
parse_headers ();
while (fgets (buffer, sizeof (buffer)-1, stdin) != NULL){
@@ -231,3 +244,49 @@ table_browser_test (void)
NULL);
}
+static void
+do_e_table_demo (const char *col_spec, const char *group_spec)
+{
+ GtkWidget *e_table, *window;
+ ETableModel *e_table_model;
+ ECell *cell_left_just;
+ ETableHeader *full_header;
+ int i;
+
+ /*
+ * Data model
+ */
+ e_table_model = e_table_simple_new (
+ col_count, row_count, value_at,
+ set_value_at, is_cell_editable, NULL);
+
+ full_header = e_table_header_new ();
+ cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
+
+ for (i = 0; i < cols; i++){
+ ETableCol *ecol = e_table_col_new (
+ i, column_labels [i],
+ 80, 20, cell_left_just,
+ g_str_equal, TRUE);
+
+ e_table_header_add_column (full_header, ecol, i);
+ }
+
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ e_table = e_table_new (full_header, e_table_model, col_spec, group_spec);
+
+ gtk_container_add (GTK_CONTAINER (window), e_table);
+
+ gtk_widget_show (e_table);
+ gtk_widget_show (window);
+}
+
+void
+e_table_test (void)
+{
+ load_data ();
+ do_e_table_demo ("0,1,2,3,4", NULL);
+ do_e_table_demo ("0,1,2,3,4", "3");
+ do_e_table_demo ("0,1,2,3,4", "3,4");
+}