beginning of the keyboard navigation.

1999-11-27  Miguel de Icaza  <miguel@gnu.org>

	* e-table-item.c (eti_event): beginning of the keyboard navigation.

	* e-table-model.c (e_table_model_row_changed): new function.
	(e_table_model_cell_changed): new function.
	(e_table_model_class_init): New signals.

	* e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
	wrong.
	(eti_select): Repaint selected region.
	(eti_request_region_redraw): Fix range.
	(eti_draw): Correct offset computation here.
	(e_table_item_class_init): New method: row_selection, handles the
	selection.

	Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.

	Focusing and selection should be correct now.

svn path=/trunk/; revision=1441
This commit is contained in:
Miguel de Icaza
1999-11-28 03:12:22 +00:00
committed by Arturo Espinosa
parent be9d0c05db
commit 8d75b6689b
41 changed files with 1444 additions and 450 deletions

View File

@ -1,3 +1,23 @@
1999-11-27 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_event): beginning of the keyboard navigation.
* e-table-model.c (e_table_model_row_changed): new function.
(e_table_model_cell_changed): new function.
(e_table_model_class_init): New signals.
* e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
wrong.
(eti_select): Repaint selected region.
(eti_request_region_redraw): Fix range.
(eti_draw): Correct offset computation here.
(e_table_item_class_init): New method: row_selection, handles the
selection.
Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.
Focusing and selection should be correct now.
1999-11-26 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_realize): Compute height using the ecell

View File

@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
ECellTextView *text_view = (ECellTextView *) ecell_view;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
if (e_table_model_get_selected_row (ecell->table_model) == row)
e_cell_text_start_editing (ect, col, row);
else
e_table_model_select_row (ecell->table_model, row);
return TRUE;
default:
break;
}
return FALSE;
}
static int

View File

@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
return 0;
}
static gint
@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2)
int col, int row, gboolean selected, int x1, int y1, int x2, int y2)
{
E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw (
ecell_view, drawable, col, row, x1, y1, x2, y2);
ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int

View File

@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2);
int col, int row, gboolean selected, int x1, int y1, int x2, int y2);
gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row);
void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, int x1, int y1, int x2, int y2);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2);
void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2);
void e_cell_unfocus (ECellView *ecell_view);
int e_cell_height (ECellView *ecell_view, int col, int row);

View File

@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
g_return_if_fail (id != NULL);
g_return_if_fail (width >= 0);
g_return_if_fail (min_width >= 0);
g_return_if_fail (width >= min_width);
g_return_if_fail (compare != NULL);
g_return_val_if_fail (id != NULL, NULL);
g_return_val_if_fail (width >= 0, NULL);
g_return_val_if_fail (min_width >= 0, NULL);
g_return_val_if_fail (width >= min_width, NULL);
g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);

View File

@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
#if 0
int
e_table_group_size (ETableGroup *etg)
{
g_return_if_fail (etg != NULL);
g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
#endif

View File

@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);

View File

@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
ETableCol **new_ptr;
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
ve_table_header_get_selected (ETableHeader *eth)
e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;

View File

@ -1,19 +1,35 @@
/*
* E-table-item.c: A view of a Table.
* E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
*
* TODO:
* Add a border to the thing, so that focusing works properly.
*
*/
#include <config.h>
#include <stdio.h>
#include <gtk/gtksignal.h>
#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
#define FOCUSED_BORDER 2
static GnomeCanvasItemClass *eti_parent_class;
enum {
ROW_SELECTION,
LAST_SIGNAL
};
static gint eti_signals [LAST_SIGNAL] = { 0, };
enum {
ARG_0,
ARG_TABLE_HEADER,
@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
*
* We might want to optimize this to only realize the unique e-cells:
* ie, a strings-only table, uses the same e-cell for every column, and
* we might want to avoid realizing each e-cell.
*/
static void
eti_realize_cell_views (ETableItem *eti)
{
@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
/*
* During unrealization: we invoke every e-cell (one per column in the current
* setup) to dispose all resources allocated
*/
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
ETableCol *col = e_table_header_get_column (eti->header, i);
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
/*
* GnomeCanvasItem::update method
*/
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
/*
* eti_remove_table_model:
*
* Invoked to release the table model associated with this ETableItem
*/
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
gtk_signal_disconnect (eti->table_model_change_id);
gtk_signal_disconnect (eti->table_model_selection_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
/*
* eti_remove_header_model:
*
* Invoked to release the header model associated with this ETableItem
*/
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
gtk_signal_disconnect (eti->header_structure_change_id);
gtk_signal_disconnect (eti->header_dim_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_structure_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
/*
* eti_row_height:
*
* Returns the height used by row @row. This does not include the one-pixel
* used as a separator between rows
*/
static int
eti_row_height (ETableItem *eti, int row)
{
@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
/*
* eti_get_height:
*
* Returns the height of the ETableItem.
*
* The ETableItem might compute the whole height by asking every row its
* size. There is a special mode (designed to work when there are too
* many rows in the table that performing the previous step could take
* too long) set by the ETableItem->length_threshold that would determine
* when the height is computed by using the first row as the size for
* every other row in the ETableItem.
*/
static int
eti_get_height (ETableItem *eti)
{
@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
/*
* Callback routine: invoked when the ETableModel has suffered a change
*/
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
/*
* eti_request_redraw:
*
* Queues a canvas redraw for the entire ETableItem.
*/
static void
eti_request_redraw (ETableItem *eti)
{
@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
/*
* Computes the distance from @start_col to @end_col in pixels.
*/
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
/*
* Computes the distance between @start_row and @end_row in pixels
*/
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
/*
* eti_request_region_redraw:
*
* Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
* This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
*
* The @border argument is a number of pixels around the region that should also be queued
* for redraw. This is typically used by the focus routines to queue a redraw for the
* border as well.
*/
static void
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
width = eti_col_diff (eti, start_col, end_col);
height = eti_row_diff (eti, start_col, end_row);
width = eti_col_diff (eti, start_col, end_col + 1);
height = eti_row_diff (eti, start_row, end_row + 1);
gnome_canvas_request_redraw (canvas,
eti->x1 + x1, eti->y1 + y1,
eti->y1 + width + 1,
eti->x1 + height + 1);
eti->x1 + x1 - border,
eti->y1 + y1 - border,
eti->x1 + x1 + width + 1 + border,
eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
eti_request_region_redraw (eti, 0, row, eti->cols, row);
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
/*
* GtkObject::destroy method
*/
static void
eti_destroy (GtkObject *object)
{
@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
/*
* Gdk Resource allocation
*/
window = canvas_widget->window;
eti->fill_gc = canvas_widget->style->white_gc;
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
/*
*
*/
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
gdk_gc_unref (eti->focus_gc);
eti->focus_gc = NULL;
eti_unrealize_cell_views (eti);
eti->height = 0;
@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
GdkFont *font;
char text [40];
font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
#if 0
{
GdkFont *font;
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
font = GTK_WIDGET (canvas)->style->font;
sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2);
gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1);
sprintf (text, "%d:%d\n", col, row);
gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text));
}
#endif
}
@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
int heights;
int f_x1, f_x2, f_y1, f_y2;
gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
x1 = eti->x1;
x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
int xd;
y2 += eti_row_height (eti, row);
y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
if (col == eti->focused_col && row == eti->focused_row){
f_x1 = xd;
f_x2 = xd + ecol->width;
f_y1 = yd;
f_y2 = yd + height;
f_found = TRUE;
}
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
/*
* Draw focus
*/
if (f_found){
printf ("FOUD: %d %d %d %d!\n",
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
gdk_draw_rectangle (
drawable, eti->focus_gc, FALSE,
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
}
}
static double
@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
y1 = 0;
y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
static void
eti_select (ETableItem *eti, int col, int row)
{
eti->selected_col = col;
eti->selected_row = row;
}
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
if (eti->selected_row == row && eti->selected_col == col){
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
} else
eti_select (eti, col, row);
} else {
/*
* Focus the cell, and select the row
*/
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
case GDK_KEY_PRESS:
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
if (eti->focused_col > 0)
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
break;
case GDK_Right:
if ((eti->focused_col + 1) < eti->cols)
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
break;
case GDK_Up:
if (eti->focused_row > 0)
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
break;
case GDK_Down:
if ((eti->focused_row + 1) < eti->rows)
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
break;
default:
}
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
/*
* ETableItem::row_selection method
*/
static void
eti_row_selection (ETableItem *eti, int row, gboolean selected)
{
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
if (selected)
eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
else
eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
}
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
ETableItemClass *eti_class = (ETableItemClass *) object_class;
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
eti_class->row_selection = eti_row_selection;
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
}
GtkType
@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
eti->focused_row = row;
eti->focused_row = row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_row == -1)
return;
{
const int col = eti->focused_col;
const int row = eti->focused_row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
eti->focused_col = -1;
eti->focused_row = -1;
}
const GSList *
e_table_item_get_selection (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
return eti->selection;
}
GtkSelectionMode
e_table_item_get_selection_mode (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
return eti->selection_mode;
}
void
e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (selection_mode == GTK_SELECTION_BROWSE ||
selection_mode == GTK_SELECTION_EXTENDED){
g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
}
eti->selection_mode = selection_mode;
}
gboolean
e_table_item_is_row_selected (ETableItem *eti, int row)
{
g_return_val_if_fail (eti != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return TRUE;
else
return FALSE;
}
void
e_table_item_unselect_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (e_table_item_is_row_selected (eti, row)){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
row, 0);
}
}
void
e_table_item_select_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
switch (eti->selection_mode){
case GTK_SELECTION_SINGLE:
if (eti->selection){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GPOINTER_TO_INT (eti->selection->data), 0);
}
g_slist_free (eti->selection);
eti->selection = NULL;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
case GTK_SELECTION_MULTIPLE:
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
default:
}
}

View File

@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
GdkGC *focus_gc;
unsigned int draw_grid:1;
@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
int selected_col, selected_row;
GSList *selection;
GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
/*
* Focus
*/
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
/*
* Selection
*/
void e_table_item_select_row (ETableItem *e_table_Item, int row);
void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
/*
* Handling the selection
*/
const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
void e_table_item_set_selection_mode (ETableItem *e_table_Item,
GtkSelectionMode selection_mode);
gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
int row);
#endif /* _E_TABLE_ITEM_H_ */

View File

@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
MODEL_ROW_CHANGED,
MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
static guint etm_signals [LAST_SIGNAL] = { 0, };
static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
e_table_model_column_count (ETableModel *etable)
e_table_model_column_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->column_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
e_table_model_column_name (ETableModel *etable, int col)
e_table_model_column_name (ETableModel *e_table_model, int col)
{
return ETM_CLASS (etable)->column_name (etable, col);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
e_table_model_row_count (ETableModel *etable)
e_table_model_row_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->row_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
e_table_model_value_at (ETableModel *etable, int col, int row)
e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->value_at (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data);
}
gboolean
e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
GSList *l;
ETableModel *etable = (ETableModel *) object;
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
etm_signals [MODEL_CHANGED] =
e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
etm_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
e_table_model_signals [MODEL_ROW_CHANGED] =
gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1, GTK_TYPE_INT);
e_table_model_signals [MODEL_CELL_CHANGED] =
gtk_signal_new ("model_cell_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
}
static void
e_table_model_init (ETableModel *etm)
{
etm->row_selected = -1;
gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
(GtkObjectInitFunc) e_table_model_init,
(GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
etm_signals [MODEL_CHANGED]);
}
#if 0
int
e_table_model_max_col_width (ETableModel *etm, int col)
{
const int nvals = e_table_model_row_count (etm);
int max = 0;
int row;
for (row = 0; row < nvals; row++){
int w;
w = e_table_model_cell_width (etm, col, i);
if (w > max)
max = w;
}
return max;
}
#endif
void
e_table_model_select_row (ETableModel *etm, int row)
{
gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
etm->row_selected = row;
e_table_model_signals [MODEL_CHANGED]);
}
void
e_table_model_unselect_row (ETableModel *etm, int row)
e_table_model_row_changed (ETableModel *e_table_model, int row)
{
if (etm->row_selected != -1){
gtk_signal_emit (
GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
etm->row_selected, 0);
}
etm->row_selected = -1;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_ROW_CHANGED], row);
}
gint
e_table_model_get_selected_row (ETableModel *etm)
void
e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
return etm->row_selected;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}

View File

@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
/* Temporary. I swear */
int row_selected;
} ETableModel;
typedef struct {
@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
void (*model_changed) (ETableModel *etm);
void (*row_selection) (ETableModel *etc, int row, gboolean selected);
void (*model_changed) (ETableModel *etm);
void (*model_row_changed) (ETableModel *etm, int row);
void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
void e_table_model_select_row (ETableModel *e_table_model, int row);
gint e_table_model_get_selected_row (ETableModel *e_table_model);
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
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_ */

View File

@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){

View File

@ -1,3 +1,23 @@
1999-11-27 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_event): beginning of the keyboard navigation.
* e-table-model.c (e_table_model_row_changed): new function.
(e_table_model_cell_changed): new function.
(e_table_model_class_init): New signals.
* e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
wrong.
(eti_select): Repaint selected region.
(eti_request_region_redraw): Fix range.
(eti_draw): Correct offset computation here.
(e_table_item_class_init): New method: row_selection, handles the
selection.
Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.
Focusing and selection should be correct now.
1999-11-26 Miguel de Icaza <miguel@gnu.org>
* e-table-item.c (eti_realize): Compute height using the ecell

View File

@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
ECellTextView *text_view = (ECellTextView *) ecell_view;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
if (e_table_model_get_selected_row (ecell->table_model) == row)
e_cell_text_start_editing (ect, col, row);
else
e_table_model_select_row (ecell->table_model, row);
return TRUE;
default:
break;
}
return FALSE;
}
static int

View File

@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
return 0;
}
static gint
@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2)
int col, int row, gboolean selected, int x1, int y1, int x2, int y2)
{
E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw (
ecell_view, drawable, col, row, x1, y1, x2, y2);
ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int

View File

@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2);
int col, int row, gboolean selected, int x1, int y1, int x2, int y2);
gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row);
void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, int x1, int y1, int x2, int y2);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2);
void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2);
void e_cell_unfocus (ECellView *ecell_view);
int e_cell_height (ECellView *ecell_view, int col, int row);

View File

@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
g_return_if_fail (id != NULL);
g_return_if_fail (width >= 0);
g_return_if_fail (min_width >= 0);
g_return_if_fail (width >= min_width);
g_return_if_fail (compare != NULL);
g_return_val_if_fail (id != NULL, NULL);
g_return_val_if_fail (width >= 0, NULL);
g_return_val_if_fail (min_width >= 0, NULL);
g_return_val_if_fail (width >= min_width, NULL);
g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);

View File

@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
#if 0
int
e_table_group_size (ETableGroup *etg)
{
g_return_if_fail (etg != NULL);
g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
#endif

View File

@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);

View File

@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
ETableCol **new_ptr;
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
ve_table_header_get_selected (ETableHeader *eth)
e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;

View File

@ -1,19 +1,35 @@
/*
* E-table-item.c: A view of a Table.
* E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
*
* TODO:
* Add a border to the thing, so that focusing works properly.
*
*/
#include <config.h>
#include <stdio.h>
#include <gtk/gtksignal.h>
#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
#define FOCUSED_BORDER 2
static GnomeCanvasItemClass *eti_parent_class;
enum {
ROW_SELECTION,
LAST_SIGNAL
};
static gint eti_signals [LAST_SIGNAL] = { 0, };
enum {
ARG_0,
ARG_TABLE_HEADER,
@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
*
* We might want to optimize this to only realize the unique e-cells:
* ie, a strings-only table, uses the same e-cell for every column, and
* we might want to avoid realizing each e-cell.
*/
static void
eti_realize_cell_views (ETableItem *eti)
{
@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
/*
* During unrealization: we invoke every e-cell (one per column in the current
* setup) to dispose all resources allocated
*/
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
ETableCol *col = e_table_header_get_column (eti->header, i);
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
/*
* GnomeCanvasItem::update method
*/
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
/*
* eti_remove_table_model:
*
* Invoked to release the table model associated with this ETableItem
*/
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
gtk_signal_disconnect (eti->table_model_change_id);
gtk_signal_disconnect (eti->table_model_selection_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
/*
* eti_remove_header_model:
*
* Invoked to release the header model associated with this ETableItem
*/
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
gtk_signal_disconnect (eti->header_structure_change_id);
gtk_signal_disconnect (eti->header_dim_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_structure_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
/*
* eti_row_height:
*
* Returns the height used by row @row. This does not include the one-pixel
* used as a separator between rows
*/
static int
eti_row_height (ETableItem *eti, int row)
{
@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
/*
* eti_get_height:
*
* Returns the height of the ETableItem.
*
* The ETableItem might compute the whole height by asking every row its
* size. There is a special mode (designed to work when there are too
* many rows in the table that performing the previous step could take
* too long) set by the ETableItem->length_threshold that would determine
* when the height is computed by using the first row as the size for
* every other row in the ETableItem.
*/
static int
eti_get_height (ETableItem *eti)
{
@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
/*
* Callback routine: invoked when the ETableModel has suffered a change
*/
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
/*
* eti_request_redraw:
*
* Queues a canvas redraw for the entire ETableItem.
*/
static void
eti_request_redraw (ETableItem *eti)
{
@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
/*
* Computes the distance from @start_col to @end_col in pixels.
*/
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
/*
* Computes the distance between @start_row and @end_row in pixels
*/
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
/*
* eti_request_region_redraw:
*
* Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
* This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
*
* The @border argument is a number of pixels around the region that should also be queued
* for redraw. This is typically used by the focus routines to queue a redraw for the
* border as well.
*/
static void
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
width = eti_col_diff (eti, start_col, end_col);
height = eti_row_diff (eti, start_col, end_row);
width = eti_col_diff (eti, start_col, end_col + 1);
height = eti_row_diff (eti, start_row, end_row + 1);
gnome_canvas_request_redraw (canvas,
eti->x1 + x1, eti->y1 + y1,
eti->y1 + width + 1,
eti->x1 + height + 1);
eti->x1 + x1 - border,
eti->y1 + y1 - border,
eti->x1 + x1 + width + 1 + border,
eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
eti_request_region_redraw (eti, 0, row, eti->cols, row);
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
/*
* GtkObject::destroy method
*/
static void
eti_destroy (GtkObject *object)
{
@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
/*
* Gdk Resource allocation
*/
window = canvas_widget->window;
eti->fill_gc = canvas_widget->style->white_gc;
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
/*
*
*/
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
gdk_gc_unref (eti->focus_gc);
eti->focus_gc = NULL;
eti_unrealize_cell_views (eti);
eti->height = 0;
@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
GdkFont *font;
char text [40];
font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
#if 0
{
GdkFont *font;
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
font = GTK_WIDGET (canvas)->style->font;
sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2);
gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1);
sprintf (text, "%d:%d\n", col, row);
gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text));
}
#endif
}
@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
int heights;
int f_x1, f_x2, f_y1, f_y2;
gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
x1 = eti->x1;
x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
int xd;
y2 += eti_row_height (eti, row);
y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
if (col == eti->focused_col && row == eti->focused_row){
f_x1 = xd;
f_x2 = xd + ecol->width;
f_y1 = yd;
f_y2 = yd + height;
f_found = TRUE;
}
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
/*
* Draw focus
*/
if (f_found){
printf ("FOUD: %d %d %d %d!\n",
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
gdk_draw_rectangle (
drawable, eti->focus_gc, FALSE,
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
}
}
static double
@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
y1 = 0;
y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
static void
eti_select (ETableItem *eti, int col, int row)
{
eti->selected_col = col;
eti->selected_row = row;
}
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
if (eti->selected_row == row && eti->selected_col == col){
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
} else
eti_select (eti, col, row);
} else {
/*
* Focus the cell, and select the row
*/
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
case GDK_KEY_PRESS:
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
if (eti->focused_col > 0)
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
break;
case GDK_Right:
if ((eti->focused_col + 1) < eti->cols)
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
break;
case GDK_Up:
if (eti->focused_row > 0)
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
break;
case GDK_Down:
if ((eti->focused_row + 1) < eti->rows)
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
break;
default:
}
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
/*
* ETableItem::row_selection method
*/
static void
eti_row_selection (ETableItem *eti, int row, gboolean selected)
{
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
if (selected)
eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
else
eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
}
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
ETableItemClass *eti_class = (ETableItemClass *) object_class;
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
eti_class->row_selection = eti_row_selection;
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
}
GtkType
@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
eti->focused_row = row;
eti->focused_row = row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_row == -1)
return;
{
const int col = eti->focused_col;
const int row = eti->focused_row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
eti->focused_col = -1;
eti->focused_row = -1;
}
const GSList *
e_table_item_get_selection (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
return eti->selection;
}
GtkSelectionMode
e_table_item_get_selection_mode (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
return eti->selection_mode;
}
void
e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (selection_mode == GTK_SELECTION_BROWSE ||
selection_mode == GTK_SELECTION_EXTENDED){
g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
}
eti->selection_mode = selection_mode;
}
gboolean
e_table_item_is_row_selected (ETableItem *eti, int row)
{
g_return_val_if_fail (eti != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return TRUE;
else
return FALSE;
}
void
e_table_item_unselect_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (e_table_item_is_row_selected (eti, row)){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
row, 0);
}
}
void
e_table_item_select_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
switch (eti->selection_mode){
case GTK_SELECTION_SINGLE:
if (eti->selection){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GPOINTER_TO_INT (eti->selection->data), 0);
}
g_slist_free (eti->selection);
eti->selection = NULL;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
case GTK_SELECTION_MULTIPLE:
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
default:
}
}

View File

@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
GdkGC *focus_gc;
unsigned int draw_grid:1;
@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
int selected_col, selected_row;
GSList *selection;
GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
/*
* Focus
*/
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
/*
* Selection
*/
void e_table_item_select_row (ETableItem *e_table_Item, int row);
void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
/*
* Handling the selection
*/
const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
void e_table_item_set_selection_mode (ETableItem *e_table_Item,
GtkSelectionMode selection_mode);
gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
int row);
#endif /* _E_TABLE_ITEM_H_ */

View File

@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
MODEL_ROW_CHANGED,
MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
static guint etm_signals [LAST_SIGNAL] = { 0, };
static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
e_table_model_column_count (ETableModel *etable)
e_table_model_column_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->column_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
e_table_model_column_name (ETableModel *etable, int col)
e_table_model_column_name (ETableModel *e_table_model, int col)
{
return ETM_CLASS (etable)->column_name (etable, col);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
e_table_model_row_count (ETableModel *etable)
e_table_model_row_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->row_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
e_table_model_value_at (ETableModel *etable, int col, int row)
e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->value_at (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data);
}
gboolean
e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
GSList *l;
ETableModel *etable = (ETableModel *) object;
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
etm_signals [MODEL_CHANGED] =
e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
etm_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
e_table_model_signals [MODEL_ROW_CHANGED] =
gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1, GTK_TYPE_INT);
e_table_model_signals [MODEL_CELL_CHANGED] =
gtk_signal_new ("model_cell_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
}
static void
e_table_model_init (ETableModel *etm)
{
etm->row_selected = -1;
gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
(GtkObjectInitFunc) e_table_model_init,
(GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
etm_signals [MODEL_CHANGED]);
}
#if 0
int
e_table_model_max_col_width (ETableModel *etm, int col)
{
const int nvals = e_table_model_row_count (etm);
int max = 0;
int row;
for (row = 0; row < nvals; row++){
int w;
w = e_table_model_cell_width (etm, col, i);
if (w > max)
max = w;
}
return max;
}
#endif
void
e_table_model_select_row (ETableModel *etm, int row)
{
gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
etm->row_selected = row;
e_table_model_signals [MODEL_CHANGED]);
}
void
e_table_model_unselect_row (ETableModel *etm, int row)
e_table_model_row_changed (ETableModel *e_table_model, int row)
{
if (etm->row_selected != -1){
gtk_signal_emit (
GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
etm->row_selected, 0);
}
etm->row_selected = -1;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_ROW_CHANGED], row);
}
gint
e_table_model_get_selected_row (ETableModel *etm)
void
e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
return etm->row_selected;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}

View File

@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
/* Temporary. I swear */
int row_selected;
} ETableModel;
typedef struct {
@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
void (*model_changed) (ETableModel *etm);
void (*row_selection) (ETableModel *etc, int row, gboolean selected);
void (*model_changed) (ETableModel *etm);
void (*model_row_changed) (ETableModel *etm, int row);
void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
void e_table_model_select_row (ETableModel *e_table_model, int row);
gint e_table_model_get_selected_row (ETableModel *e_table_model);
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
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_ */

View File

@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){

View File

@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
#include "e-cursors.h"
#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
printf ("Value at %d,%d set to %s\n", col, row, val);
printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean

View File

@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
#include "e-cursors.h"
#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
printf ("Value at %d,%d set to %s\n", col, row, val);
printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean

View File

@ -64,13 +64,14 @@ ect_unrealize (ECellView *ecv)
}
static void
ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
ECellTextView *text_view = (ECellTextView *) ecell_view;
GdkRectangle rect;
const char *str = e_table_model_value_at (ecell_view->ecell->table_model, col, row);
int selected = e_table_model_get_selected_row (ecell_view->ecell->table_model) == row;
int xoff, w;
rect.x = x1;
@ -94,6 +95,7 @@ ect_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1
xoff = ((x2 - x1) - gdk_text_width (text_view->font, str, strlen (str))) / 2;
break;
default:
xoff = 0;
g_warning ("Can not handle GTK_JUSTIFY_FILL");
break;
}
@ -135,12 +137,12 @@ ect_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
switch (event->type){
case GDK_BUTTON_PRESS:
if (e_table_model_get_selected_row (ecell->table_model) == row)
e_cell_text_start_editing (ect, col, row);
else
e_table_model_select_row (ecell->table_model, row);
return TRUE;
default:
break;
}
return FALSE;
}
static int

View File

@ -24,7 +24,9 @@ ec_unrealize (ECellView *e_cell)
}
static void
ec_draw (ECellView *ecell_view, GdkDrawable *drawable, int col, int row, int x1, int y1, int x2, int y2)
ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
g_warning ("e-cell-draw invoked\n");
}
@ -33,6 +35,7 @@ static gint
ec_event (ECellView *ecell_view, GdkEvent *event, int col, int row)
{
g_warning ("e-cell-event invoked\n");
return 0;
}
static gint
@ -109,10 +112,10 @@ e_cell_unrealize (ECellView *ecell_view)
void
e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2)
int col, int row, gboolean selected, int x1, int y1, int x2, int y2)
{
E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw (
ecell_view, drawable, col, row, x1, y1, x2, y2);
ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
}
int

View File

@ -32,7 +32,7 @@ typedef struct {
ECellView *(*realize) (ECell *, GnomeCanvas *canvas);
void (*unrealize) (ECellView *);
void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
int col, int row, int x1, int y1, int x2, int y2);
int col, int row, gboolean selected, int x1, int y1, int x2, int y2);
gint (*event) (ECellView *ecell_view, GdkEvent *event, int col, int row);
void (*focus) (ECellView *ecell, int col, int row, int x1, int y1, int x2, int y2);
void (*unfocus) (ECellView *ecell);
@ -43,8 +43,9 @@ GtkType e_cell_get_type (void);
void e_cell_event (ECellView *ecell_view, GdkEvent *event, int col, int row);
ECellView *e_cell_realize (ECell *ecell, GnomeCanvas *canvas);
void e_cell_unrealize (ECellView *ecell_view);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, int x1, int y1, int x2, int y2);
void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
int col, int row, gboolean selected,
int x1, int y1, int x2, int y2);
void e_cell_focus (ECellView *ecell_view, int col, int row, int x1, int y1, int x2, int y2);
void e_cell_unfocus (ECellView *ecell_view);
int e_cell_height (ECellView *ecell_view, int col, int row);

View File

@ -17,11 +17,11 @@ e_table_col_new (const char *id, int width, int min_width,
{
ETableCol *etc;
g_return_if_fail (id != NULL);
g_return_if_fail (width >= 0);
g_return_if_fail (min_width >= 0);
g_return_if_fail (width >= min_width);
g_return_if_fail (compare != NULL);
g_return_val_if_fail (id != NULL, NULL);
g_return_val_if_fail (width >= 0, NULL);
g_return_val_if_fail (min_width >= 0, NULL);
g_return_val_if_fail (width >= min_width, NULL);
g_return_val_if_fail (compare != NULL, NULL);
etc = g_new (ETableCol, 1);

View File

@ -76,10 +76,11 @@ e_table_group_append_child (ETableGroup *etg, ETableGroup *child)
etg->u.children = g_slist_append (etg->u.children, child);
}
#if 0
int
e_table_group_size (ETableGroup *etg)
{
g_return_if_fail (etg != NULL);
g_return_val_if_fail (etg != NULL, 0);
if (etg->is_leaf)
return e_table_model_height (etg->u.table);
@ -96,3 +97,4 @@ e_table_group_size (ETableGroup *etg)
}
}
#endif

View File

@ -7,6 +7,7 @@
* Copyright 1999, Helix Code, Inc.
*/
#include <config.h>
#include <gtk/gtksignal.h>
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-cursors.h"
@ -124,7 +125,6 @@ ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableHeaderItem *ethi;
int v;
item = GNOME_CANVAS_ITEM (o);
ethi = E_TABLE_HEADER_ITEM (o);

View File

@ -121,8 +121,6 @@ eth_update_offsets (ETableHeader *eth)
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
ETableCol **new_ptr;
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (tc != NULL);
@ -204,7 +202,6 @@ ETableCol **
e_table_header_get_columns (ETableHeader *eth)
{
ETableCol **ret;
int i;
g_return_val_if_fail (eth != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
@ -226,7 +223,7 @@ e_table_header_selection_ok (ETableHeader *eth)
}
int
ve_table_header_get_selected (ETableHeader *eth)
e_table_header_get_selected (ETableHeader *eth)
{
int i;
int selected = 0;

View File

@ -1,19 +1,35 @@
/*
* E-table-item.c: A view of a Table.
* E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
* Copyright 1999, Helix Code, Inc.
*
* TODO:
* Add a border to the thing, so that focusing works properly.
*
*/
#include <config.h>
#include <stdio.h>
#include <gtk/gtksignal.h>
#include <gdk/gdkkeysyms.h>
#include "e-table-item.h"
#include "e-cell.h"
#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
#define FOCUSED_BORDER 2
static GnomeCanvasItemClass *eti_parent_class;
enum {
ROW_SELECTION,
LAST_SIGNAL
};
static gint eti_signals [LAST_SIGNAL] = { 0, };
enum {
ARG_0,
ARG_TABLE_HEADER,
@ -24,6 +40,14 @@ enum {
ARG_LENGHT_THRESHOLD
};
/*
* During realization, we have to invoke the per-ecell realize routine
* (On our current setup, we have one e-cell per column.
*
* We might want to optimize this to only realize the unique e-cells:
* ie, a strings-only table, uses the same e-cell for every column, and
* we might want to avoid realizing each e-cell.
*/
static void
eti_realize_cell_views (ETableItem *eti)
{
@ -43,14 +67,16 @@ eti_realize_cell_views (ETableItem *eti)
}
}
/*
* During unrealization: we invoke every e-cell (one per column in the current
* setup) to dispose all resources allocated
*/
static void
eti_unrealize_cell_views (ETableItem *eti)
{
int i;
for (i = 0; i < eti->n_cells; i++){
ETableCol *col = e_table_header_get_column (eti->header, i);
e_cell_unrealize (eti->cell_views [i]);
eti->cell_views [i] = NULL;
}
@ -59,6 +85,9 @@ eti_unrealize_cell_views (ETableItem *eti)
}
/*
* GnomeCanvasItem::update method
*/
static void
eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
{
@ -75,14 +104,21 @@ eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}
/*
* eti_remove_table_model:
*
* Invoked to release the table model associated with this ETableItem
*/
static void
eti_remove_table_model (ETableItem *eti)
{
if (!eti->table_model)
return;
gtk_signal_disconnect (eti->table_model_change_id);
gtk_signal_disconnect (eti->table_model_selection_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
eti->table_model_selection_id);
gtk_object_unref (GTK_OBJECT (eti->table_model));
eti->table_model_change_id = 0;
@ -90,14 +126,21 @@ eti_remove_table_model (ETableItem *eti)
eti->table_model = NULL;
}
/*
* eti_remove_header_model:
*
* Invoked to release the header model associated with this ETableItem
*/
static void
eti_remove_header_model (ETableItem *eti)
{
if (!eti->header)
return;
gtk_signal_disconnect (eti->header_structure_change_id);
gtk_signal_disconnect (eti->header_dim_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_structure_change_id);
gtk_signal_disconnect (GTK_OBJECT (eti->header),
eti->header_dim_change_id);
gtk_object_unref (GTK_OBJECT (eti->header));
eti->header_structure_change_id = 0;
@ -105,6 +148,12 @@ eti_remove_header_model (ETableItem *eti)
eti->header = NULL;
}
/*
* eti_row_height:
*
* Returns the height used by row @row. This does not include the one-pixel
* used as a separator between rows
*/
static int
eti_row_height (ETableItem *eti, int row)
{
@ -123,6 +172,18 @@ eti_row_height (ETableItem *eti, int row)
return max_h;
}
/*
* eti_get_height:
*
* Returns the height of the ETableItem.
*
* The ETableItem might compute the whole height by asking every row its
* size. There is a special mode (designed to work when there are too
* many rows in the table that performing the previous step could take
* too long) set by the ETableItem->length_threshold that would determine
* when the height is computed by using the first row as the size for
* every other row in the ETableItem.
*/
static int
eti_get_height (ETableItem *eti)
{
@ -148,6 +209,9 @@ eti_get_height (ETableItem *eti)
return height;
}
/*
* Callback routine: invoked when the ETableModel has suffered a change
*/
static void
eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
{
@ -160,6 +224,11 @@ eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
}
/*
* eti_request_redraw:
*
* Queues a canvas redraw for the entire ETableItem.
*/
static void
eti_request_redraw (ETableItem *eti)
{
@ -170,6 +239,9 @@ eti_request_redraw (ETableItem *eti)
eti->y1 + eti->height + 1);
}
/*
* Computes the distance from @start_col to @end_col in pixels.
*/
static int
eti_col_diff (ETableItem *eti, int start_col, int end_col)
{
@ -185,6 +257,9 @@ eti_col_diff (ETableItem *eti, int start_col, int end_col)
return total;
}
/*
* Computes the distance between @start_row and @end_row in pixels
*/
static int
eti_row_diff (ETableItem *eti, int start_row, int end_row)
{
@ -198,28 +273,38 @@ eti_row_diff (ETableItem *eti, int start_row, int end_row)
return total;
}
/*
* eti_request_region_redraw:
*
* Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
* This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
*
* The @border argument is a number of pixels around the region that should also be queued
* for redraw. This is typically used by the focus routines to queue a redraw for the
* border as well.
*/
static void
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row)
eti_request_region_redraw (ETableItem *eti, int start_col, int start_row, int end_col, int end_row, int border)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
int x1, y1, width, height;
int col, row;
x1 = eti_col_diff (eti, 0, start_col);
y1 = eti_row_diff (eti, 0, start_row);
width = eti_col_diff (eti, start_col, end_col);
height = eti_row_diff (eti, start_col, end_row);
width = eti_col_diff (eti, start_col, end_col + 1);
height = eti_row_diff (eti, start_row, end_row + 1);
gnome_canvas_request_redraw (canvas,
eti->x1 + x1, eti->y1 + y1,
eti->y1 + width + 1,
eti->x1 + height + 1);
eti->x1 + x1 - border,
eti->y1 + y1 - border,
eti->x1 + x1 + width + 1 + border,
eti->y1 + y1 + height + 1 + border);
}
static void
eti_table_model_row_selection (ETableModel *table_model, int row, gboolean selected, ETableItem *eti)
{
eti_request_region_redraw (eti, 0, row, eti->cols, row);
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
}
static void
@ -282,6 +367,9 @@ eti_add_header_model (ETableItem *eti, ETableHeader *header)
GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
}
/*
* GtkObject::destroy method
*/
static void
eti_destroy (GtkObject *object)
{
@ -289,6 +377,8 @@ eti_destroy (GtkObject *object)
eti_remove_header_model (eti);
eti_remove_table_model (eti);
g_slist_free (eti->selection);
if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
(*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
@ -299,7 +389,6 @@ eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
GnomeCanvasItem *item;
ETableItem *eti;
int v;
item = GNOME_CANVAS_ITEM (o);
eti = E_TABLE_ITEM (o);
@ -343,6 +432,8 @@ eti_init (GnomeCanvasItem *item)
eti->height = 0;
eti->length_threshold = -1;
eti->selection_mode = GTK_SELECTION_SINGLE;
}
static void
@ -355,13 +446,24 @@ eti_realize (GnomeCanvasItem *item)
if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
(*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
/*
* Gdk Resource allocation
*/
window = canvas_widget->window;
eti->fill_gc = canvas_widget->style->white_gc;
gdk_gc_ref (canvas_widget->style->white_gc);
eti->grid_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
eti->focus_gc = gdk_gc_new (window);
gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->black);
gdk_gc_set_line_attributes (eti->focus_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
/*
*
*/
eti_realize_cell_views (eti);
eti->height = eti_get_height (eti);
@ -377,7 +479,9 @@ eti_unrealize (GnomeCanvasItem *item)
eti->fill_gc = NULL;
gdk_gc_unref (eti->grid_gc);
eti->grid_gc = NULL;
gdk_gc_unref (eti->focus_gc);
eti->focus_gc = NULL;
eti_unrealize_cell_views (eti);
eti->height = 0;
@ -387,26 +491,28 @@ eti_unrealize (GnomeCanvasItem *item)
}
static void
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row,
draw_cell (ETableItem *eti, GdkDrawable *drawable, int col, int row, gboolean selected,
int x1, int y1, int x2, int y2)
{
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
ECellView *ecell_view;
GdkFont *font;
char text [40];
font = GTK_WIDGET (canvas)->style->font;
ecell_view = eti->cell_views [col];
e_cell_draw (ecell_view, drawable, col, row, x1, y1, x2, y2);
e_cell_draw (ecell_view, drawable, col, row, selected, x1, y1, x2, y2);
#if 0
{
GdkFont *font;
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
font = GTK_WIDGET (canvas)->style->font;
sprintf (text, "%d:%d\n", col, row); gdk_draw_line (drawable, eti->grid_gc, x1, y1, x2, y2);
gdk_draw_line (drawable, eti->grid_gc, x1, y2, x2, y1);
sprintf (text, "%d:%d\n", col, row);
gdk_draw_text (drawable, font, eti->grid_gc, x1, y2, text, strlen (text));
}
#endif
}
@ -420,7 +526,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
int first_col, last_col, x_offset;
int first_row, last_row, y_offset, yd;
int x1, x2;
int heights;
int f_x1, f_x2, f_y1, f_y2;
gboolean f_found;
printf ("Rect: %d %d %d %d\n", x, y, width, height);
/*
@ -435,7 +542,7 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
*/
first_col = -1;
last_col = x_offset = 0;
x1 = eti->x1;
x1 = x2 = eti->x1;
for (col = 0; col < cols; col++, x1 = x2){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
@ -465,9 +572,8 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
y_offset = 0;
y1 = y2 = eti->y1;
for (row = eti->top_item; row < rows; row++, y1 = y2){
int xd;
y2 += eti_row_height (eti, row);
y2 += eti_row_height (eti, row) + 1;
if (y1 > y + height)
break;
@ -489,24 +595,49 @@ eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width,
* Draw cells
*/
yd = y_offset;
f_x1 = f_x2 = f_y1 = f_y2 = -1;
f_found = FALSE;
for (row = first_row; row < last_row; row++){
int xd, height;
gboolean selected;
height = eti_row_height (eti, row);
xd = x_offset;
printf ("paint: %d %d\n", yd, yd + height);
selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
for (col = first_col; col < last_col; col++){
ETableCol *ecol = e_table_header_get_column (eti->header, col);
draw_cell (eti, drawable, col, row, xd, yd, xd + ecol->width, yd + height);
draw_cell (eti, drawable, col, row, selected, xd, yd, xd + ecol->width, yd + height);
if (col == eti->focused_col && row == eti->focused_row){
f_x1 = xd;
f_x2 = xd + ecol->width;
f_y1 = yd;
f_y2 = yd + height;
f_found = TRUE;
}
xd += ecol->width;
}
yd += height + 1;
gdk_draw_line (drawable, eti->grid_gc,
eti->x1 - x, yd -1, eti->x1 + eti->width - x, yd -1);
}
/*
* Draw focus
*/
if (f_found){
printf ("FOUD: %d %d %d %d!\n",
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
gdk_draw_rectangle (
drawable, eti->focus_gc, FALSE,
f_x1 - 1, f_y1 - 1, f_x2 - f_x1 + 2 , f_y2 - f_y1 + 2);
}
}
static double
@ -547,7 +678,7 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
break;
}
y1 = 0;
y1 = y2 = 0;
for (row = 0; row < rows; row++, y1 = y2){
if (y < y1)
return FALSE;
@ -564,13 +695,6 @@ find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res)
return TRUE;
}
static void
eti_select (ETableItem *eti, int col, int row)
{
eti->selected_col = col;
eti->selected_row = row;
}
static int
eti_event (GnomeCanvasItem *item, GdkEvent *e)
{
@ -586,22 +710,56 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
if (!find_cell (eti, e->button.x, e->button.y, &col, &row))
return TRUE;
if (eti->selected_row == row && eti->selected_col == col){
if (eti->focused_row == row && eti->focused_col == col){
ecell_view = eti->cell_views [col];
e_cell_event (ecell_view, e, col, row);
} else
eti_select (eti, col, row);
} else {
/*
* Focus the cell, and select the row
*/
e_table_item_focus (eti, col, row);
e_table_item_select_row (eti, row);
}
break;
}
case GDK_KEY_PRESS:
if (eti->focused_col == -1)
return FALSE;
switch (e->key.keyval){
case GDK_Left:
if (eti->focused_col > 0)
e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
break;
case GDK_Right:
if ((eti->focused_col + 1) < eti->cols)
e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
break;
case GDK_Up:
if (eti->focused_row > 0)
e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
break;
case GDK_Down:
if ((eti->focused_row + 1) < eti->rows)
e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
break;
default:
}
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
case GDK_KEY_RELEASE:
if (eti->focused_col == -1)
return FALSE;
ecell_view = eti->cell_views [eti->focused_col];
e_cell_event (ecell_view, e, eti->focused_col, eti->focused_row);
break;
@ -610,12 +768,27 @@ eti_event (GnomeCanvasItem *item, GdkEvent *e)
}
return TRUE;
}
/*
* ETableItem::row_selection method
*/
static void
eti_row_selection (ETableItem *eti, int row, gboolean selected)
{
eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
if (selected)
eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
else
eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
}
static void
eti_class_init (GtkObjectClass *object_class)
{
GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
ETableItemClass *eti_class = (ETableItemClass *) object_class;
eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
object_class->destroy = eti_destroy;
@ -627,7 +800,9 @@ eti_class_init (GtkObjectClass *object_class)
item_class->draw = eti_draw;
item_class->point = eti_point;
item_class->event = eti_event;
eti_class->row_selection = eti_row_selection;
gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
@ -638,6 +813,17 @@ eti_class_init (GtkObjectClass *object_class)
GTK_ARG_WRITABLE, ARG_TABLE_Y);
gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
eti_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
}
GtkType
@ -666,16 +852,124 @@ e_table_item_get_type (void)
void
e_table_item_focus (ETableItem *eti, int col, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_col != -1)
e_table_item_unfocus (eti);
eti->focused_col = col;
eti->focused_row = row;
eti->focused_row = row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
void
e_table_item_unfocus (ETableItem *eti)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (eti->focused_row == -1)
return;
{
const int col = eti->focused_col;
const int row = eti->focused_row;
eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
}
eti->focused_col = -1;
eti->focused_row = -1;
}
const GSList *
e_table_item_get_selection (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
return eti->selection;
}
GtkSelectionMode
e_table_item_get_selection_mode (ETableItem *eti)
{
g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
return eti->selection_mode;
}
void
e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (selection_mode == GTK_SELECTION_BROWSE ||
selection_mode == GTK_SELECTION_EXTENDED){
g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
}
eti->selection_mode = selection_mode;
}
gboolean
e_table_item_is_row_selected (ETableItem *eti, int row)
{
g_return_val_if_fail (eti != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return TRUE;
else
return FALSE;
}
void
e_table_item_unselect_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
if (e_table_item_is_row_selected (eti, row)){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
row, 0);
}
}
void
e_table_item_select_row (ETableItem *eti, int row)
{
g_return_if_fail (eti != NULL);
g_return_if_fail (E_IS_TABLE_ITEM (eti));
switch (eti->selection_mode){
case GTK_SELECTION_SINGLE:
if (eti->selection){
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GPOINTER_TO_INT (eti->selection->data), 0);
}
g_slist_free (eti->selection);
eti->selection = NULL;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
case GTK_SELECTION_MULTIPLE:
if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
return;
gtk_signal_emit (
GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
GINT_TO_POINTER (row), 1);
break;
default:
}
}

View File

@ -32,6 +32,7 @@ typedef struct {
GdkGC *fill_gc;
GdkGC *grid_gc;
GdkGC *focus_gc;
unsigned int draw_grid:1;
@ -49,15 +50,39 @@ typedef struct {
*/
int length_threshold;
int selected_col, selected_row;
GSList *selection;
GtkSelectionMode selection_mode;
} ETableItem;
typedef struct {
GnomeCanvasItemClass parent_class;
void (*row_selection) (ETableItem *eti, int row, gboolean selected);
} ETableItemClass;
GtkType e_table_item_get_type (void);
/*
* Focus
*/
void e_table_item_focus (ETableItem *eti, int col, int row);
void e_table_item_unfocus (ETableItem *eti);
/*
* Selection
*/
void e_table_item_select_row (ETableItem *e_table_Item, int row);
void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
/*
* Handling the selection
*/
const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
void e_table_item_set_selection_mode (ETableItem *e_table_Item,
GtkSelectionMode selection_mode);
gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
int row);
#endif /* _E_TABLE_ITEM_H_ */

View File

@ -16,55 +16,71 @@ static GtkObjectClass *e_table_model_parent_class;
enum {
MODEL_CHANGED,
MODEL_ROW_CHANGED,
MODEL_CELL_CHANGED,
ROW_SELECTION,
LAST_SIGNAL
};
static guint etm_signals [LAST_SIGNAL] = { 0, };
static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
int
e_table_model_column_count (ETableModel *etable)
e_table_model_column_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->column_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->column_count (e_table_model);
}
const char *
e_table_model_column_name (ETableModel *etable, int col)
e_table_model_column_name (ETableModel *e_table_model, int col)
{
return ETM_CLASS (etable)->column_name (etable, col);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->column_name (e_table_model, col);
}
int
e_table_model_row_count (ETableModel *etable)
e_table_model_row_count (ETableModel *e_table_model)
{
return ETM_CLASS (etable)->row_count (etable);
g_return_val_if_fail (e_table_model != NULL, 0);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
return ETM_CLASS (e_table_model)->row_count (e_table_model);
}
void *
e_table_model_value_at (ETableModel *etable, int col, int row)
e_table_model_value_at (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->value_at (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, NULL);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
}
void
e_table_model_set_value_at (ETableModel *etable, int col, int row, void *data)
e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data)
{
return ETM_CLASS (etable)->set_value_at (etable, col, row, data);
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
return ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data);
}
gboolean
e_table_model_is_cell_editable (ETableModel *etable, int col, int row)
e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
{
return ETM_CLASS (etable)->is_cell_editable (etable, col, row);
g_return_val_if_fail (e_table_model != NULL, FALSE);
g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
}
static void
e_table_model_destroy (GtkObject *object)
{
GSList *l;
ETableModel *etable = (ETableModel *) object;
if (e_table_model_parent_class->destroy)
(*e_table_model_parent_class->destroy)(object);
}
@ -76,7 +92,7 @@ e_table_model_class_init (GtkObjectClass *object_class)
object_class->destroy = e_table_model_destroy;
etm_signals [MODEL_CHANGED] =
e_table_model_signals [MODEL_CHANGED] =
gtk_signal_new ("model_changed",
GTK_RUN_LAST,
object_class->type,
@ -84,21 +100,23 @@ e_table_model_class_init (GtkObjectClass *object_class)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
etm_signals [ROW_SELECTION] =
gtk_signal_new ("row_selection",
e_table_model_signals [MODEL_ROW_CHANGED] =
gtk_signal_new ("model_row_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, row_selection),
GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1, GTK_TYPE_INT);
e_table_model_signals [MODEL_CELL_CHANGED] =
gtk_signal_new ("model_cell_changed",
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
gtk_object_class_add_signals (object_class, etm_signals, LAST_SIGNAL);
}
static void
e_table_model_init (ETableModel *etm)
{
etm->row_selected = -1;
gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
}
GtkType
@ -112,7 +130,7 @@ e_table_model_get_type (void)
sizeof (ETableModel),
sizeof (ETableModelClass),
(GtkClassInitFunc) e_table_model_class_init,
(GtkObjectInitFunc) e_table_model_init,
(GtkObjectInitFunc) NULL,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@ -127,53 +145,31 @@ e_table_model_get_type (void)
void
e_table_model_changed (ETableModel *e_table_model)
{
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
etm_signals [MODEL_CHANGED]);
}
#if 0
int
e_table_model_max_col_width (ETableModel *etm, int col)
{
const int nvals = e_table_model_row_count (etm);
int max = 0;
int row;
for (row = 0; row < nvals; row++){
int w;
w = e_table_model_cell_width (etm, col, i);
if (w > max)
max = w;
}
return max;
}
#endif
void
e_table_model_select_row (ETableModel *etm, int row)
{
gtk_signal_emit (GTK_OBJECT (etm), etm_signals [ROW_SELECTION], row, 1);
etm->row_selected = row;
e_table_model_signals [MODEL_CHANGED]);
}
void
e_table_model_unselect_row (ETableModel *etm, int row)
e_table_model_row_changed (ETableModel *e_table_model, int row)
{
if (etm->row_selected != -1){
gtk_signal_emit (
GTK_OBJECT (etm), etm_signals [ROW_SELECTION],
etm->row_selected, 0);
}
etm->row_selected = -1;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_ROW_CHANGED], row);
}
gint
e_table_model_get_selected_row (ETableModel *etm)
void
e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
{
return etm->row_selected;
g_return_if_fail (e_table_model != NULL);
g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
gtk_signal_emit (GTK_OBJECT (e_table_model),
e_table_model_signals [MODEL_CELL_CHANGED], col, row);
}

View File

@ -11,9 +11,6 @@
typedef struct {
GtkObject base;
/* Temporary. I swear */
int row_selected;
} ETableModel;
typedef struct {
@ -32,8 +29,9 @@ typedef struct {
/*
* Signals
*/
void (*model_changed) (ETableModel *etm);
void (*row_selection) (ETableModel *etc, int row, gboolean selected);
void (*model_changed) (ETableModel *etm);
void (*model_row_changed) (ETableModel *etm, int row);
void (*model_cell_changed) (ETableModel *etm, int col, int row);
} ETableModelClass;
GtkType e_table_model_get_type (void);
@ -45,13 +43,13 @@ void *e_table_model_value_at (ETableModel *e_table_model, int col,
void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, void *data);
gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
void e_table_model_select_row (ETableModel *e_table_model, int row);
gint e_table_model_get_selected_row (ETableModel *e_table_model);
/*
* Routines for emitting signals on the e_table
*/
void e_table_model_changed (ETableModel *e_table_model);
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_ */

View File

@ -30,7 +30,6 @@ static ETableSorted *sort_ets;
static int
my_sort (const void *a, const void *b)
{
GCompareFunc comp;
ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
const int *ia = (const int *) a;
const int *ib = (const int *) b;
@ -59,7 +58,6 @@ e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
ETableSubset *etss = E_TABLE_SUBSET (ets);
const int nvals = e_table_model_row_count (source);
unsigned int *buffer;
int i;
if (e_table_subset_construct (etss, source, nvals) == NULL){

View File

@ -12,6 +12,8 @@
#include "e-table-header.h"
#include "e-table-header-item.h"
#include "e-table-item.h"
#include "e-cursors.h"
#include "e-cell-text.h"
char buffer [1024];
char **column_labels;
@ -157,7 +159,7 @@ set_value_at (ETableModel *etc, int col, int row, void *val, void *data)
g_free (table_data [row][col]);
table_data [row][col] = g_strdup (val);
printf ("Value at %d,%d set to %s\n", col, row, val);
printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
}
static gboolean