aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/table
diff options
context:
space:
mode:
authorArturo Espinosa <unammx@src.gnome.org>1999-12-12 17:20:46 +0800
committerArturo Espinosa <unammx@src.gnome.org>1999-12-12 17:20:46 +0800
commitfa895ed8e1454d4d761b8789381ca5ba464a7c93 (patch)
tree594aa949bfdb351a0cb6646bb950744c8a791c88 /widgets/table
parent863f8aa634005c6400d629c353f5fed485106fce (diff)
downloadgsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar.gz
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar.bz2
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar.lz
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar.xz
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.tar.zst
gsoc2013-evolution-fa895ed8e1454d4d761b8789381ca5ba464a7c93.zip
More work. We now have the basics for nesting working, now we need all the
More work. We now have the basics for nesting working, now we need all the interactions done properly. I want to use a new GnomeCanvasItem for the nesting parent as well. DnD will have to be done with our own protocol to provide all the feedback we want to provide. Miguel svn path=/trunk/; revision=1481
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");
+}